-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
266 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
layout: post | ||
title: 同一脚本内,kill 通过 sudo 启动的进程 | ||
tag: [Shell] | ||
categories: [Linux] | ||
--- | ||
|
||
<!--break--> | ||
|
||
# 问题 | ||
|
||
简单的说,如下脚本中的`kill`是不会生效的。 | ||
|
||
```bash | ||
#!/bin/bash | ||
set -x | ||
sudo sleep 10 & | ||
PID=$! | ||
|
||
sleep 2 | ||
sudo kill $PID | ||
|
||
sleep 1 | ||
ps aux | grep sleep | ||
``` | ||
|
||
参考: [Why does kill not work from script, but does work from terminal?](https://unix.stackexchange.com/a/625478) 。如果我没理解错的话,原因是: | ||
|
||
`sudo` 不能用来 `kill` 同一个进程组内的其他进程。 | ||
|
||
# 解决方案 | ||
|
||
这里,使用 `setsid` 来重置 `sleep` 进程的进程组(注意:不是 `sudo sleep` )。 | ||
|
||
然后,借助曾经在《 [Shell脚本中,等待所有子进程/孙进程退出](../wait-child-grandchild-quit/) 》中使用过的方法,通过查询 `sudo sleep` 的子进程的方式 `kill` 由 `sudo` 启动的 `sleep` 进程。 | ||
|
||
接下来,由于子进程退出(被 `kill`),`sudo sleep` 进程也会自动退出。 | ||
|
||
|
||
```bash | ||
#!/bin/bash | ||
set -x | ||
|
||
sudo setsid sleep 10 & | ||
PID=$! | ||
|
||
sleep 2 | ||
WPIDs=($(ps -eo pid,ppid \ | ||
| awk -v ppid=$PID '{if($2==ppid && $1!=ppid){print $1}}')) | ||
for pid in ${WPIDs[@]} ; do | ||
if ps -p $pid > /dev/null ; then | ||
sudo kill $pid | ||
fi | ||
done | ||
|
||
sleep 1 | ||
ps aux | grep sleep | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
layout: post | ||
title: 筛查二进制文件中是否包涵敏感字符 | ||
tag: [Shell] | ||
categories: [Linux] | ||
--- | ||
|
||
<!--break--> | ||
|
||
在对外发布的二进制文件中筛查敏感常量信息。比如 LOG 中包涵了设备型号。 | ||
|
||
``` | ||
find /root/path/to/releases -type f \ | ||
-exec sh -c "file -i '{}' | grep -q 'charset=binary'" \; -print \ | ||
| xargs -x strings -f | grep -i <keyword> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
--- | ||
layout: post | ||
title: 在非编译环境中运行测试程序并获取正确的覆盖率报告 | ||
tag: [GCC,Gcov] | ||
categories: [Program] | ||
--- | ||
|
||
本文针对`GCOV_PREFIX`和`GCOV_PREFIX_STRIP`的使用进行一些记录。 | ||
|
||
<!--break--> | ||
|
||
首先,准备一个简单的 C 语言程序作为测试目标。 | ||
|
||
```c | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
int foo(int a) | ||
{ | ||
return a * a; | ||
} | ||
|
||
int main(int argc, char const *argv[]) | ||
{ | ||
printf("%d\n", foo(atoi(argv[1]))); | ||
return 0; | ||
} | ||
``` | ||
在最简单的情况下,我们的情况会类似于下面的脚本。 | ||
即编译环境和运行环境都在一起。 | ||
这种情况下,只要参数设置没有问题,就可以简单的获取对应的覆盖率报告。 | ||
```bash | ||
#!/bin/bash | ||
gcc main.c -o test -lgcov -coverage | ||
./test 2 | ||
lcov -c -d $(pwd) -o test.info | ||
genhtml test.info -o doc | ||
``` | ||
|
||
但是,很多情况下,我们都需要将测试程序移动到其他环境中运行。 | ||
比如下面的脚本模拟了在`Docker`中运行测试程序的情况。 | ||
|
||
简单的运行一下,我们会发现,覆盖率报告生成失败了。 | ||
原因是, `lcov` 找不到 `.gcda` 文件。 | ||
|
||
|
||
```bash | ||
#!/bin/bash | ||
|
||
gcc main.c -o test -lgcov -coverage | ||
|
||
docker run -v $(pwd):/home/test \ | ||
ubuntu:20.04 /home/test/test 2 | ||
|
||
lcov -c -d $(pwd) -o test.info | ||
genhtml test.info -o doc | ||
``` | ||
|
||
解决的方法也很简单。在目标环境中设置`GCOV_PREFIX`和`GCOV_PREFIX_STRIP`这两个环境变量。 | ||
其中: | ||
|
||
* `GCOV_PREFIX` 是测试程序运行的位置。 | ||
* `GCOV_PREFIX_STRIP` 是编译测试程序时,源代码所在路径的深度。 | ||
|
||
|
||
```bash | ||
#!/bin/bash | ||
|
||
gcc main.c -o test -lgcov -coverage | ||
|
||
echo "#!/bin/bash" > startup.sh | ||
echo "export GCOV_PREFIX=/home/test" >> startup.sh | ||
echo "export GCOV_PREFIX_STRIP=\$(echo $(pwd) | awk -F\"/\" '{print NF-1}')" \ | ||
>> startup.sh | ||
echo "/home/test/test 2" >> startup.sh | ||
chmod +x startup.sh | ||
docker run -v $(pwd):/home/test -w /home/test \ | ||
ubuntu:20.04 /home/test/startup.sh | ||
|
||
lcov -c -d $(pwd) -o test.info | ||
genhtml test.info -o doc | ||
``` | ||
|
||
上述例子其实还不够精准的描述更加复杂的情况。 | ||
例如,当我们需要在多个`Docker`中并行运行同一段代码时(这种情况常见于动态链接库), | ||
同时运行的程序会竞争`.gcda`文件。引发写冲突破坏`.gcda`文件。 | ||
为了避免类似的问题,我们可能需要将测试程序拷贝多份。 | ||
|
||
参照下面的脚本,我们将编译出来的测试程序移动到了源代码以外的路径(`new`),去执行 | ||
(脚本并没有模拟并行运行的情况,毕竟测试程序太简单了,一瞬间就退出了)。 | ||
|
||
这种情况下,直接执行测试程序,就会由于缺少信息而无法生成覆盖率报告。 | ||
这些信息其实是保存在`.gcno`文件中。 | ||
|
||
参照下面的脚本,将`main.gcno`同样复制到新的路径下,然后再次运行测试程序。 | ||
覆盖率报告可以顺利的生成了。 | ||
|
||
|
||
```bash | ||
#!/bin/bash | ||
|
||
gcc main.c -o test -lgcov -coverage | ||
install -d new | ||
install test new | ||
|
||
echo "#!/bin/bash" > new/startup.sh | ||
echo "export GCOV_PREFIX=/home/test" >> new/startup.sh | ||
echo "export GCOV_PREFIX_STRIP=\$(echo $(pwd) | awk -F\"/\" '{print NF-1}')" \ | ||
>> new/startup.sh | ||
echo "/home/test/test 2" >> new/startup.sh | ||
chmod +x new/startup.sh | ||
|
||
cp main.gcno new/ | ||
docker run -v $(pwd)/new:/home/test/ -w /home/test \ | ||
ubuntu:20.04 /home/test/startup.sh | ||
|
||
lcov -c -d $(pwd)/new -o test.info | ||
genhtml test.info -o doc | ||
``` | ||
|
||
简单总结一下。 | ||
|
||
某工程代码的存放路径为`/path/to/proj`,其中有一个源文件存放在`a/b.c`。 | ||
编译生成的`a.out`转移到目标系统的`/usr/bin`下运行。 | ||
|
||
此时,需要进行如下工作: | ||
|
||
* 将`/path/to/proj/a/b.gcno`复制到目标环境的`/usr/bin/a/b.gcno`; | ||
* 设置环境变量`GCOV_PREFIX=/usr/bin`; | ||
* 设置环境变量`GCOV_PREFIX_STRIP=3`。(`/path/to/proj`是三层)。 | ||
|
||
运行时,`a.out`会根据调试信息去寻找`/path/to/proj/a/b.gcno`。 | ||
但是,由于设置了`GCOV_PREFIX`,这个目标会调整为`/usr/bin/path/to/proj/a/b.gcno`。 | ||
然后,由于设置了`GCOV_PREFIX_STRIP`,将`/usr/bin/`后面的三级路径删除,变成了 | ||
`/usr/bin/a/b.gcno`。 | ||
在这里,`a.out`找到了我们提前复制进去的`b.gcno`文件。 | ||
并在同样的位置生成`/usr/bin/a/b.gcda`文件。 | ||
|
||
有了`.gcno`和`.gcda`文件,就可以生成测试报告了。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters