我有这个脚本(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
之前将其存储在变量中会得到正确的结果。有什么帮助吗?
提前感谢!
因此,首先我们从终端执行./test.sh
。因此,我们有一个进程名为test.sh
。
process_count=`pgrep 'test.sh' | wc -l`
由backticks调用的命令替换运行子shell。子shell是一个单独的进程,具有相同的进程名称test.sh
。因此,现在有两个具有不同pid的进程,它们的进程名称为test.sh
。因此CCD_ 7返回两行。
例如,可以使用进行检查
process_count=$(
ps -e -o pid,comm | grep 'test.sh' >&2
echo BASHPID=$BASHPID $=$$ >&2
pgrep 'test.sh' | wc -l
)
stderr:上的输出
495463 test.sh
495466 test.sh
BASHPID=495466 $=495463
495466
是子shell的pid,495463
是父shell进程的pid。
当你这样做:
pids=`pgrep 'test.sh'`;
这会输出单个pid。这是因为bash有一个优化,在特定的情况下(例如没有trap
s(,当一个shell中只剩下一个进程执行时,它会进行优化,不调用fork()+exec()
,而是只调用exec
,因为不会有下一个进程运行,所以它可以退出。进程名为test.sh
的内部子shell只存在很短的一段时间,子shell检测到只有一个命令要运行,因此跳过fork()
,只执行exec("pgrep")
,成为进程名为pgrep
的进程。这就是为什么在这种情况下你看不到另一个pid。
注意:请不要使用反勾号`。请改用$(...)
。
额外:更多潜艇!以下
echo "$(echo "$(echo "$(pgrep 'test.sh' | wc -l)")")"
# would output 4