【问题标题】:pgrep {process_name} | wc -l returning wrong resultspgrep {进程名称} | wc -l 返回错误结果
【发布时间】:2020-05-06 15:53:23
【问题描述】:

我有这个脚本(test.sh):

#!/bin/bash

echo "pgreg --- start"
pgrep 'test.sh'
echo "pgrep --- end"

process_count=`pgrep 'test.sh' | wc -l`
echo "process_count = $process_count"

pids=`pgrep 'test.sh'`;
fixed_count_process=`echo $pids | wc -w`
echo "pids = $pids";
echo "fixed_count_process = $fixed_count_process"

这个脚本的输出总是:

pgreg --- start
56516
pgrep --- end
process_count = 2
pids = 56516
fixed_count_process = 1

我找不到任何合乎逻辑的解释,为什么在将pgrep 的输出传递给wc 之前将其存储在变量中会给出正确的结果。有什么帮助吗?

提前致谢!

【问题讨论】:

    标签: linux shell wc


    【解决方案1】:

    所以首先我们从终端执行./test.sh。所以我们有一个进程名称为test.sh的进程。

    process_count=`pgrep 'test.sh' | wc -l`
    

    反引号调用的命令替换运行一个子shell。子shell 是一个单独的进程,具有相同的进程名称test.sh。因此,现在有两个具有不同 pid 的进程具有进程名称 test.sh。因此pgrep 返回两行。

    这可以通过以下方式进行检查:

    process_count=$(
            ps -e -o pid,comm | grep 'test.sh' >&2
            echo BASHPID=$BASHPID \$=$$ >&2
            pgrep 'test.sh' | wc -l
    )
    

    在标准错误上输出:

     495463 test.sh
     495466 test.sh
    BASHPID=495466 $=495463
    

    495466 是子 shell 的 pid,495463 是父 shell 进程的 pid。

    当你这样做时:

    pids=`pgrep 'test.sh'`;
    

    这会输出一个 pid。这是因为 bash 有一个优化,在特定情况下(例如,没有 traps),当只有一个进程在 shell 中执行时,它会优化并且不调用 fork()+exec(),而是只调用 exec ,因为不会有下一个进程运行,所以只能退出。进程名为test.sh的内部子shell只存在很短的时间,子shell检测到只有一个命令可以运行,所以跳过fork(),直接执行exec("pgrep"),变成进程名为@的进程987654338@。这就是为什么在这种情况下您看不到另一个 pid。

    注意:请不要使用反引号`。请改用$(...)

    额外:更多子shell!以下

    echo "$(echo "$(echo "$(pgrep 'test.sh' | wc -l)")")"
    # would output 4
    

    【讨论】:

    • 感谢您的回答!在那种情况下,如果反引号运行一个新的子shell,为什么pids=`pgrep 'test.sh'`; 会返回一个 pid?
    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 2020-04-28
    相关资源
    最近更新 更多