You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测带参数的Bash脚本是否已运行及pgrep与wc命令计数异常问题排查

问题原因分析与解决方法

你遇到的核心矛盾是:pgrep -f ... | wc -l的统计结果总是比实际运行的脚本进程数多1,而echo $processes | wc -w却能得到正确值,主要原因如下:

1. pgrep会临时匹配自身进程

当你在脚本内部执行pgrep -f时,pgrep进程启动后会扫描当前系统的所有进程,包括它自己。如果你的正则表达式没有精确限制匹配范围(比如你用了+这类正则特殊字符,且没有锚定行首行尾),pgrep会把自己的PID也输出出来。

虽然这个PID在pgrep退出后立刻消失,但wc -l会统计所有输出的行数(包括这个临时PID的行),导致结果多1:

  • 首次运行时,实际只有1个脚本进程,pgrep输出脚本PID+自身PID,wc -l返回2
  • 第二次运行时,实际有2个脚本进程,pgrep输出两个脚本PID+自身PID,wc -l返回3

你看不到pgrep自身PID的原因是:pgrep输出自己的PID后立刻退出,这个PID对应的进程很快被系统回收,终端输出时可能被缓冲覆盖或未显示。

2. echo $processes | wc -w计数正确的原因

你脚本里的$(pgrep -f "$0 +$*$")存在语法错误(缺少闭合的)),导致processes变量没有正确捕获到pgrep的全部输出(只保留了脚本的PID),因此wc -w统计到的是正确的进程数量。即使语法正确,当你用$(pgrep ...)捕获输出时,pgrep已经退出,它的PID会被系统回收,bash展开变量时可能会忽略无效PID(或换行被替换为空格,临时PID的行被合并后过滤)。


解决方法:准确统计带参数的脚本进程

要避免pgrep匹配自身,同时精确区分带不同参数的脚本进程,你可以采用以下改进方案:

方法1:精确锚定正则表达式

用^和$锚定正则表达式,确保只匹配完全以脚本名+参数开头和结尾的命令行,这样pgrep自己的进程(以pgrep开头)不会被匹配:

#!/bin/bash
script_full_cmd="$0 $*"
echo "inside test.sh, script command: $script_full_cmd"

echo "精确匹配的pgrep结果:"
pgrep -f "^$script_full_cmd$"

echo "统计进程数量:"
count=$(pgrep -f "^$script_full_cmd$" | wc -l)
echo $count

sleep 300

方法2:排除当前脚本的子进程

用$$(当前脚本的PID)过滤掉pgrep这类子进程:

count=$(pgrep -f "$0 $*" | grep -v $$ | wc -l)

方法3:用ps命令精确匹配

通过ps结合grep过滤,避免匹配自身进程:

count=$(ps aux | grep -E "^[^ ]+ +[^ ]+ +.+$0 $*$" | grep -v grep | wc -l)

内容的提问来源于stack exchange,提问作者Frédéric Charrier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 07:43:12