pgrep 命令是不是有什么问题?加-f 参数 pid 每次都变

286 天前
 dyllen

在 shell 脚本里面这样获取 pid:

pid=`pgrep $projectName`
echo "'$pid'"

发现有字符长度限制,太长返回空,后面改成这样:

pid=`pgrep -f $projectName`
echo "'$pid'"

问题来了加了-f参数后,获取到的 pid 的值变这样了:

'3054607
3206134'

取到了两个 pid 值,第一个是正确的,第二个是完全不相干的,每次还变。 然后我杀死进程之后再执行,他还是能获取的一个完全不相关的 pid 出来。

不管我要找的进程在不在他总是有值,还不一定对,我不用脚本执行,就在控制台执行单纯pgrep -f $projectName就没问题。

这什么问题?

1220 次点击
所在节点    Linux
19 条回复
lhbc
286 天前
怀疑这么基础的软件有问题之前,还是先怀疑下你的参数和系统的进程列表比较好
你给个变量谁知道什么情况啊
lhbc
286 天前
另外,如果同一个进程名称有多个进程,pgrep 是会获取到多个 pid 的
liuchao719
286 天前
这个不想干的进程是不是就是 pgrep 本身?
julyclyde
286 天前
@liuchao719 pgrep 会过滤掉 pgrep 自己的,不会发生你猜的这种情况

第二个应该是线程号
lhbc
286 天前
@liuchao719 不会,pgrep 里有逻辑把自己的 pid 给去掉了
dyllen
286 天前
@lhbc 我肯定是对过了,才会来发问的。

下面是我测试的内容。

我的测试脚本内容:

```shell
#!/bin/bash

set -e

pid=`pgrep -f $1`
echo "'$pid'"
```
`./test.sh abc`结果:
```shell
~$ ./test.sh abc
'3234022
3354825'

~$ ./test.sh abc
'3234022
3354899'

~$ ./test.sh abc
'3234022
3354906'
```

控制台执行的输出结果:

```shell
~$ echo `pgrep -f abc`
3234022

~$ echo `pgrep -f abc`
3234022

~$ echo `pgrep -f abc`
3234022
```

`ps -ef | grep`出来出去 grep 的进程,就一个运行进程。

这里我把名字用 abc 替换了,实际也是这么简单,英文字母下划线组成的 10 个字符长度的名字,没特殊字符。
llh880808
286 天前
提供一个思路,我这边做实验得到的结果是
1. pgrep $name 得到 1 个结果
2. pgrep -f $name 得到 2 个结果
3. ps -ef | grep 多出来的那个 pid ,发现多出来的 pid 是 CMD 列包含`$name`字样(比如路径名包含),但并不是我预期的
4. pgrep -h 查看-f 参数的含义是“ use full process name to match”,猜想,-f 参数会使用整个进程名(包括参数)去匹配,很容易匹配到预期外的结果
dyllen
286 天前
@llh880808 是加了-f 参数,得到两个结果,第二个完全不相干的 pid 了
Alias4ck
286 天前
感觉是你字符串的问题你可以-l 打印完整进程名看看

dyllen
286 天前
@llh880808 不加-f 参数,有长度限制,名称超过 15 个字符就匹配不出来了,搜索下来都是说加-f 参数解决,加了之后我发现会匹配出来两个结果。所以现在我是就截取前 15 个字符来匹配。。。这样暂时没问题。
dyllen
286 天前
@Alias4ck

`test.sh`加了-l ,结果:

~$ ./test.sh abc
'3234022 abc
3403871 test.sh'


第二个 pid 是脚本本身。
Alias4ck
286 天前
那就合理的解释了为啥每次都会变了 因为匹配到自身了

找到一个跟你差不多的问题
https://stackoverflow.com/questions/59790449/bash-script-strange-pgrep-behaviour
lhbc
286 天前
./test.sh abc
这个命令本身被匹配到了
lhbc
286 天前
不要把进程名称作为脚本的参数提交
julyclyde
286 天前
不过这问题应该换个角度(不是可以,而是应该)
你可能需要把这个进程托管给 systemd 管理,而不是自己寨一套脚本出来
dyllen
283 天前
@julyclyde 这又不是线上用的,就是为了方便自己开发重启应用用的,我那小脚本功能是拉取代码,编译,结束原来的进程,启动新的进程。
dyllen
283 天前
@lhbc 这就不太好了,那只能自己再过滤一遍结果了,或者只取前 15 个字符不加-f 参数来匹配了,这样也没有问题。
julyclyde
283 天前
@dyllen 让旧进程自己写个 pid 文件吧
dyllen
280 天前
@julyclyde 这样也可以,pid 记录下来

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/961199

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX