In a script that contains the following lines and is called by ansible (via ssh and then sudo), about 4 out of 5 times, I end up in the if branch, although the process I'm trying to ps
and grep
is permanently running. The Count:
echoed in that case is "0".
PROC=[a]sdf # brackets, so we don't grep the grep process itself
# sleep 0.1
PID=(`ps -ef|grep -E "$PROC"|awk '{print $2}'`)
PIDLEN=`echo "${#PID[@]}"`
if [ "PIDLEN" -ne 1 ]; then
echo \"$PROC\" does not designate a single, unique process. Count: "$PIDLEN"
Now the funny thing is, when I uncomment the "sleep 0.1" line, I never get into the if branch, which is what I would expect.
This script is started in detached mode using nohup, which may be related. The playbook looks something like this:
- shell:
cmd: nohup ./script.sh </dev/null >/tmp/out 2>/tmp/err &
Update
Irrelevant to my question, but someone in the comments seems to believe that pgrep
is always preferable to a ps|grep
combo. Just to prove that that's not necessarily the case - it is in fact the reason I do not use pgrep here - try this in debian 10:
$ sleep 1000 $(seq 1 1200)|wc -c&
[1] 13821
$ ps -ef|grep [1]200|wc -l
1
$ pgrep -f 1200|wc -l
0
$ pgrep -f 1038|wc -l
1
$ pgrep -f 1039|wc -l
0
$ pgrep -af 1038|wc -c
4102 # 5-digit PID + SPACE + 4096 chars
$ ps -ef|grep [1]200|wc -c
4952
This shows that pgrep greps/prints only 4096 characters per process, whereas ps -ef does more than that. (Obviously ps|grepping for a number is not a safe thing to do in general, I'm just using this to prove the point.)
All the above is easily verifiable for anyone using this Dockerfile:
FROM debian:10
RUN apt-get clean
RUN apt-get update
RUN apt-get install -y --no-install-recommends procps
which can be built and run using these commands
docker build -t debian10-pgrep-vs-ps .
docker run --rm -it debian10-pgrep-vs-ps
ps -ef|grep -E "$PROC"|awk '{print $2}'
thegrep -E "$PROC"
may find itself. NEVER use thatps -fe | grep | awk | sed
[censored], usepgrep "$PROC"
orpgrep -f "$PROC"
. – Mar 03 '20 at 11:44ps -fe | grep | grep | awk
. Do you think thatps -fe
will print lines longer than 4096 characters? Think again. Yoursleep .1
may bring a little commotion, causing the processes from the pipeline to be scheduled a bit differently, and thegrep
to find itself. It's absolutely pointless to reason about such things. – Mar 03 '20 at 22:02ps -ef
prints more than 4096 characters (per process), whereaspgrep -f
does not. I don't want to use ps, but it seems I have to. – Evgeniy Berezovsky Mar 03 '20 at 22:08sleep 3600 $(seq 1 10000) &
.ps -fe | grep 10000
=>grep 10000
. Where'ssleep
ifps -fe
prints more than 4096 characters per process? Here it isgrep 10000 /proc/[0-9]*/cmdline
=>/proc/6613/cmdline
.cat /proc/6613/comm
=>sleep
. – Mar 03 '20 at 22:19grep 10000
togrep -E [1]0000
, and you won't grep yourself. Not even sure if the '-E' is necessary here. – Evgeniy Berezovsky Mar 03 '20 at 22:23