pgrep 数出来的进程数总是多一个?先看自匹配这条坑

举报
yd_242458115 发表于 2026/11/09 12:01:59 2026/11/09
【摘要】 用 pgrep -f 统计进程数,结果总比实际多一个,或者 pkill 明明执行了却杀错了东西。这篇讲清自匹配是怎么发生的、为什么 -f 更容易踩,以及三种规避写法(方括号技巧、pidof、加 -- 与白名单)。

现象

用 pgrep 统计某个脚本有没有在跑,结果总比实际多一个。或者反过来:pkill 执行完,本该被杀的那个进程还在,别的东西被误杀了。

这不是 pgrep 的 bug,是自匹配:你写的这条 pgrep 命令,它自己的命令行里就含有你要匹配的那个关键词,于是它把自己也算进去了。

一个最小复现:

pgrep -af run-daily.sh

输出里会看到类似这样的两行:

1234567 bash run-daily.sh
1234999 bash -c pgrep -af run-daily.sh

第二行就是执行这条命令的 shell 本身。如果把它接进 wc -l 做判断:

pgrep -f run-daily.sh | wc -l

在"其实没在跑"的情况下也会返回 1,于是脚本以为任务正在运行,跳过执行——这是最典型的误判形态。

为什么 -f 更容易踩

两种匹配模式的区别:

写法 | 匹配范围 | 自匹配风险

pgrep 名字 | 只比对进程名(comm,通常 15 字符截断) | 低,因为 shell 的进程名是 bash

pgrep -f 字符串 | 比对整条命令行 | 高,因为你的命令自己就含有这个字符串

所以只要用了 -f,并且关键词出现在你自己这条命令里,就必然自匹配。

三种规避写法

一、方括号技巧(最通用)

把关键词的首字母写成字符类:

pgrep -f "[r]un-daily.sh"

对方括号在正则里代表"匹配 r 这个字符",所以它匹配的真实进程名是 run-daily.sh;而这条命令自己的命令行里写的是 [r]un-daily.sh,字面上不等于 run-daily.sh,于是不自匹配。

这个技巧对所有"在命令行里搜自己"的场景都通用,例如:

ps aux | grep "[n]ginx"

二、用 pidof 或 systemctl(更稳)

如果不是必须按命令行匹配,优先用不依赖字符串比对的接口:

pidof run-daily.sh
systemctl is-active 你的服务名

systemctl is-active 返回 active / inactive / activating,是状态机口径,不会自匹配,也不会因为进程名截断而漏判。

三、排除自身 PID

需要精确控制时,把当前 shell 的 PID 及其父进程排除掉:

pgrep -f run-daily.sh | grep -v -e "^$$\$" -e "^$PPID\$"

实际用起来比前两种麻烦,只在脚本里确实要拿进程列表做后续处理时才值得。

顺带一个同源坑:pkill 也会自匹配

pkill -f 关键词 同样会把自己的命令行纳入候选。更麻烦的是,pkill 杀到自己的父 shell 时,脚本会在半路莫名其妙退出——表现为"命令执行了,但后面的代码没跑"。

所以 pkill 更推荐用精确目标:

pkill -f "[r]un-daily.sh"

或者干脆用服务管理:

systemctl stop 你的服务名

判断清单

  • 数字总比预期大 1 → 先怀疑自匹配,把命令换成方括号写法再数。
  • 在 ssh 远程执行里数不对 → 远程那层 shell 的命令行也会被匹配,同样处理。
  • 进程名超过 15 字符 → 不加 -f 可能因截断匹配不上,此时必须用 -f,那就要防自匹配。
  • 拿 pgrep | wc -l 当"是否在跑"的判据 → 换成 systemctl is-active 或 pgrep -c 加方括号写法。

小结

pgrep -f / pkill -f / ps | grep 这三个组合都会自匹配,原因是命令行里含有被搜索的字面量。最省事的解法就是方括号写法:[r]un-daily.sh。如果本来就有服务管理器,用 systemctl is-active 比数进程更可靠。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。