我有一个bash脚本( ScreamDaemon.sh ),其中添加了一个已经运行的示例的检查。
numscr=`ps aux | grep ScreamDaemon.sh | wc -l`;
if [ "${numscr}" -gt "2" ]; then
echo "an instance of ScreamDaemon still running";
exit 0;
fi
通常,如果没有另一个脚本副本在运行, ps aux | grep ScreamDaemon.sh | wc -l </ strong>应该返回 2 (它应该找到自己和 grep ScreamDaemon.sh ),但它会返回 3 。
所以,我试着分析一下发生了什么,并在添加一些回声后看到:
我在剧本中添加了一些行
ps aux | grep ScreamDaemon.sh
ps aux | grep ScreamDaemon.sh | wc -l
str=`ps aux | grep ScreamDaemon.sh`
echo $str
numscr=`ps aux | grep ScreamDaemon.sh | wc -l`;
echo $numscr
有一个输出:
pamela 27894 0.0 0.0 106100 1216 pts/1 S+ 13:41 0:00 /bin/bash ./ScreamDaemon.sh
pamela 27899 0.0 0.0 103252 844 pts/1 S+ 13:41 0:00 grep ScreamDaemon.sh
2
pamela 27894 0.0 0.0 106100 1216 pts/1 S+ 13:41 0:00 /bin/bash ./ScreamDaemon.sh pamela 27903 0.0 0.0 106100 524 pts/1 S+ 13:41 0:00 /bin/bash ./ScreamDaemon.sh pamela 27905 0.0 0.0 103252 848 pts/1 S+ 13:41 0:00 grep ScreamDaemon.sh
3
我还尝试在`ps aux |中添加 sleep 命令grep ScreamDaemon.sh;睡1m` 并从并行终端看到有多少实例 ps aux | grep ScreamDaemon.sh 显示:
[pamela@pm03 ~]$ ps aux | grep ScreamDaemon.sh
pamela 28394 0.0 0.0 106100 1216 pts/1 S+ 14:23 0:00 /bin/bash ./ScreamDaemon.sh
pamela 28403 0.0 0.0 106100 592 pts/1 S+ 14:23 0:00 /bin/bash ./ScreamDaemon.sh
pamela 28408 0.0 0.0 103252 848 pts/9 S+ 14:23 0:00 grep ScreamDaemon.sh
所以,似乎 str =`ps aux | grep ScreamDaemon.sh` 与之相反 ps aux | grep ScreamDaemon.sh 发现了两个 ScreamDaemon.sh 的实例,但为什么呢?这个额外的 ScreamDaemon.sh 副本来自何处?
这是pstree -ap命令的输出
│ ├─sshd,27806
│ │ └─sshd,27808
│ │ └─bash,27809
│ │ └─ScreamDaemon.sh,28731 ./ScreamDaemon.sh
│ │ └─ScreamDaemon.sh,28740 ./ScreamDaemon.sh
│ │ └─sleep,28743 2m
答案 0 :(得分:2)
ps
中多次显示?当隐式创建子shell的任何构造都在进行中时,这是典型的。例如,在bash中:
echo foo | bar
...创建一个新的shell分叉副本以运行echo
,并使用自己的ps
实例。类似地:
( bar; echo done )
...创建一个新的子shell,让子shell运行外部命令bar
,然后使子shell执行echo
。
类似地:
foo=$(bar)
...为命令替换创建一个子shell,在那里运行bar
(可能exec
'命令并使用子shell,但这不保证),并将其输出读入父母。
现在,这是如何回答你的问题的?因为
result=$(ps aux | grep | wc)
...在子shell中运行ps
命令 ,它本身会创建一个额外的bash实例。
使用锁文件。
参见例如:
请注意,我强烈建议使用基于flock
的变体。
答案 1 :(得分:0)
当然,您找到其他流程的原因是:
一个进程正在运行子shell(命令执行`..`
)
包含在您的行中:numscr=`ps aux | grep ScreamDaemon.sh | wc -l`;
这是最简单的答案。
但是,我想就您的代码提出一些其他建议:
首先,引用你的扩展,它应该是:echo "$str"
不这样做会让几条线路变成长线。
其次,您可以使用:grep [S]creamDaemon.sh
来避免匹配grep命令本身。
第三,在变量中捕获命令一次,然后从变量中计算行数。在这种情况下,它没有问题,但对于动态过程,一次捕获和以下捕获计数可能会产生不同的结果。
第四,养成使用$(...)
command substitutions而不是更容易出错的习惯(特别是在嵌套时)`...`
。
### Using a file as the simplest way to capture the output of a command
### that is running in this shell (not a subshell).
ps aux | grep "[S]creamDaemon.sh" > "/tmp/tmpfile$$.txt"
str="$(< "/tmp/tmpfile$$.txt")" ### get the value of var "str"
rm "/tmp/tmpfile$$.txt" ### erase the file used ($$ is pid).
numscr="$(echo "$str" | wc -l)" ### count the number of lines.
echo "$numscr" ### present results.
echo "$str"
str="$( ps aux | grep "[S]creamDaemon.sh" )" ### capture var "str".
numscr="$(echo "$str" | wc -l)" ### count the number of lines.
echo "$numscr" ### present results.
echo "$str"
### The only bashim is the `$(<...)`, change to `$(cat ...)` if needed.
@CharlesDuffy很好地涵盖了flock
,please read it。