脚本内ps aux和`ps aux`之间的不同结果

我有一个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应该返回2 (它应该find自己和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; 睡眠1米`并从并行terminal看到有多less实例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.shfindScreamDaemon.sh的两个实例,但是为什么? ScreamDaemon.sh这个额外的副本是从哪里来的?

这是pstree -ap命令的输出

  │ ├─sshd,27806 │ │ └─sshd,27808 │ │ └─bash,27809 │ │ └─ScreamDaemon.sh,28731 ./ScreamDaemon.sh │ │ └─ScreamDaemon.sh,28740 ./ScreamDaemon.sh │ │ └─sleep,28743 2m 

Solutions Collecting From Web of "脚本内ps aux和`ps aux`之间的不同结果"

为什么单个bash脚本可以在ps多次显示?

当隐式创建子外壳的任何构造都在使用时,这是典型的。 例如,在bash中:

 echo foo | bar 

…用它自己的ps实例创建一个新的shell分支副本来运行echo 。 同理:

 ( bar; echo done ) 

…创建一个新的子shell,使该子shell运行外部命令bar ,然后使子shell执行echo

同理:

 foo=$(bar) 

…为命令替换创建一个子shell,在那里运行bar (可能exec命令并使用子shell,但不能保证),并将其输出读入父代。

现在,这是如何回答你的问题? 因为

 result=$(ps aux | grep | wc) 

在一个子shell中运行这个ps命令,它自己创建一个额外的bash实例。


我怎样才能正确地确保我的脚本只有一个副本正在运行?

使用一个锁文件。

例如见:

  • 如何防止脚本同时运行?
  • 确保只有一个Bash脚本的一个实例正在运行的最佳方法是什么?

请注意,我强烈建议使用基于flock的变体。

当然,你找到一个额外的过程的原因是因为:

一个进程运行子shell(命令执行`..`
包含在你的行中: numscr=`ps aux | grep ScreamDaemon.sh | wc -l`; numscr=`ps aux | grep ScreamDaemon.sh | wc -l`;

这是最简单的答案。


不过,我想就你的代码提出一些额外的建议:

首先,引用你的扩展,应该是: echo "$str"
不这样做是让几条线崩溃成一条长线。

其次,你可以使用: grep [S]creamDaemon.sh来避免匹配grep命令本身。

第三,在一个变量中只捕获一次命令,然后从变量中计数线。 在这种情况下,它没有任何问题,但是对于动态进程,一次捕获和下面的捕获次数可能会给出不同的结果。

第四,养成使用$(...) 命令替换的习惯,而不是更容易出错(特别是在嵌套时) `...`

 ### 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相当不错, 请仔细阅读 。