Linux 脚本中ps aux和`ps aux`之间的不同结果
我有一个bash脚本(creamdaemon.sh),其中添加了一个检查示例,确保它没有运行Linux 脚本中ps aux和`ps aux`之间的不同结果,linux,bash,shell,Linux,Bash,Shell,我有一个bash脚本(creamdaemon.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应该
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(它应该找到自己和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
我还尝试将sleep命令添加到`ps aux|grep ScreamDaemon.sh;休眠1m`并从并行终端查看有多少实例显示:
[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.sh`
违背
ps aux| grep.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
为什么单个bash脚本可以在ps
中多次显示?
当隐式创建子shell的任何构造都在运行时,这是典型的。例如,在bash中:
echo foo | bar
…创建shell的新分叉副本,以使用其自己的ps
实例运行echo
。同样地:
( bar; echo done )
foo=$(bar)
…创建一个新的子shell,让该子shell运行外部命令bar
,然后让该子shell执行echo
同样地:
( bar; echo done )
foo=$(bar)
…为命令替换创建子shell,在其中运行bar
(可能执行命令并使用子shell,但这不是保证),并将其输出读入父级
现在,这如何回答你的问题?因为
result=$(ps aux | grep | wc)
…在子shell中运行ps
命令,它本身会创建一个额外的bash实例
如何正确地确保只有一个脚本副本正在运行? 使用锁定文件 例如,见:
请注意,我强烈建议使用基于
群体的变体。当然,您找到附加流程的原因是:
一个进程正在运行(命令执行的子shell)
包括在您的行中:numscr=`ps aux|grep creamdaemon.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.
####使用文件作为捕获命令输出的最简单方式
###在这个shell(不是子shell)中运行的。
ps aux | grep“[S]creamDaemon.sh”>“/tmp/tmpfile$$.txt”
str=“$(<”/tmp/tmpfile$$.txt”)###获取var“str”的值
rm“/tmp/tmpfile$$.txt”####删除使用的文件($$是pid)。
numsr=“$(echo“$str”| wc-l)”###计算行数。
回显“$numscr”####显示结果。
回显“$str”
str=“$(ps aux | grep”[S]creamDaemon.sh”)”###capture var“str”。
numsr=“$(echo“$str”| wc-l)”###计算行数。
回显“$numscr”####显示结果。
回显“$str”
###唯一的bashim是“$”(它从搜索结果中排除了grep ScreamDaemon.sh,但它仍然找到了2个实例,而不是1个您可以键入并粘贴回pstree-ap
?(您可以删除不需要的行)找不到一种方法如何将其以可读的形式放在这里:(因此,类似这样的东西:sshd,27806->sshd,27808->bash,27809->creamdaemon.sh,28731./creamdaemon.sh->creamdaemon.sh,28740./creamdaemon.sh->sleep,287432m
将其放在原始消息中可能还会提到pgrep
——如果可用,最好使用ps|grep
习惯用法。-f
参数再次匹配。)st完整的命令行;因此:pgrep-f ScreamDaemon.sh