Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

linux - Different results between ps aux and `ps aux` inside a script

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...