脚本中的ps aux和`ps aux`之间的结果不同 [英] Different results between ps aux and `ps aux` inside a script

查看:205
本文介绍了脚本中的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 <​​/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

解决方案

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

当隐式创建子shell的任何构造都在起作用时,这是典型的.例如,在bash中:

echo foo | bar

...使用其自己的ps实例创建外壳的新的派生副本以运行echo.同样:

( bar; echo done )

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

类似地:

foo=$(bar)

...创建一个用于命令替换的子shell,在其中运行bar(可能使用exec进行命令并使用该子shell,但这不能保证),并将其输出读入父级. /p>

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

result=$(ps aux | grep | wc)

...在子外壳中运行ps命令 ,该外壳本身会创建一个额外的bash实例.


如何正确确保脚本的一个副本正在运行?

使用锁定文件.

例如参见:

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

I have a bash script (ScreamDaemon.sh) inside which a check that example of it isn't running already is added.

numscr=`ps aux | grep ScreamDaemon.sh | wc -l`;
if [ "${numscr}" -gt "2" ]; then
  echo "an instance of ScreamDaemon still running";
  exit 0;
fi

Normally, if there are no another copy of script running, ps aux | grep ScreamDaemon.sh | wc -l should return 2 (it should find itself and grep ScreamDaemon.sh), but it returns 3.

So, I try to analyse what happens and after adding some echoes see this:

there are lines I have added into the script

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

there is an output:

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

I also tried to add the sleep command right inside `ps aux | grep ScreamDaemon.sh; sleep 1m` and see from the parallel terminal how many instances ps aux|grep ScreamDaemon.sh shows:

[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

So, it seems that str=`ps aux | grep ScreamDaemon.sh` contrary to ps aux | grep ScreamDaemon.sh found two instances of ScreamDaemon.sh, but why? Where this additional copy of ScreamDaemon.sh come from?

This is an output of pstree -ap command

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

解决方案

Why can a single bash script show up multiple times in ps?

This is typical when any constructs which implicitly create a subshell are in play. For instance, in bash:

echo foo | bar

...creates a new forked copy of the shell to run the echo, with its own ps instance. Similarly:

( bar; echo done )

...creates a new subshell, has that subshell run the external command bar, and then has the subshell perform the echo.

Similarly:

foo=$(bar)

...creates a subshell for the command substitution, runs bar in there (potentially exec'ing the command and consuming the subshell, but this is not guaranteed), and reads its output into the parent.

Now, how does this answer your question? Because

result=$(ps aux | grep | wc)

...runs that ps command in a subshell, which itself creates an extra bash instance.


How can I properly ensure that only one copy of my script is running?

Use a lockfile.

See for instance:

Note that I strongly suggest use of a flock-based variant.

这篇关于脚本中的ps aux和`ps aux`之间的结果不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆