Confirmation about pgrep returning itself
The answer is already in the comments to my question, but I figure I'll close this out with an official answer.
The piece of information I was missing is that
When bash is invoked as sh it behaves as a POSIX sh, not bash. – Jörg W Mittag Jan 23 at 23:31
So yes, pgrep was behaving normally. But when you call it from a Ruby script via backticks, you still need to filter out 'pgrep'
pgrep {process_name} | wc -l returning wrong results
So at first we do ./test.sh
from the terminal. So we have a single process with process name test.sh
.
process_count=`pgrep 'test.sh' | wc -l`
The command substitution invoked by backticks runs a subshell. The subshell is a separate process and has the same process name test.sh
. So there are now two processes with different pids that are having the process name test.sh
. Thus pgrep
returns two lines.
This could be for example inspected with:
process_count=$(
ps -e -o pid,comm | grep 'test.sh' >&2
echo BASHPID=$BASHPID \$=$$ >&2
pgrep 'test.sh' | wc -l
)
with outputs on stderr:
495463 test.sh
495466 test.sh
BASHPID=495466 $=495463
The 495466
is the pid of the subshell and 495463
is the pid of the parent shell process.
When you do:
pids=`pgrep 'test.sh'`;
this outputs a single pid. This is because bash has an optimization, that on specific circumstances (ex. no trap
s) when only one process is left to execute in a shell, it optimizes and doesn't call fork()+exec()
instead it calls just exec
, because there will be no next process to run, so it can just exit. The inner subshell with the process name test.sh
exists only for a short moment, the subshell detects that there is only a single command to run, so it skips fork()
, just executes exec("pgrep")
and becomes a process with process name pgrep
. That is why you do not see another pid in this case.
Notes: Please do not use backticks `. Use $(...)
instead.
Extra: More subshells! The following
echo "$(echo "$(echo "$(pgrep 'test.sh' | wc -l)")")"
# would output 4
pgrep command not returning PID
Normally pgrep
applies the search pattern to process names. The process name in this case is python
and not motion_sensor.py
. If you want to grep for the full path rather than just the process name you need to pass -f
:
pgrep -u www-data -f motion_sensor.py
Check man pgrep
pgrep returning true in makefile but not in shell
I think it's finding the command coming from the makefile itself. make
is executing something like:
/bin/bash -c 'if pgrep -f askdfkasdfj ; then kill $$(pgrep -f askdfkasdfj); fi'
This contains askdfkasdfj
in the -c
argument, so it matches.
But I'm not sure why this didn't happen as well when you used ps aux | grep
.
bash script variable substitution problem
It's happening because at the time your script is running it also
contains mypgrm
in its name like that:
bash ./test.sh mypgrm
and therefore is reported by pgrep -f
. You can filter it out like
that:
pgrep -f "$1" | grep -v "^$$\$"
or use a little trick and pass a name of the program in the form that
wouldn't be visible to pgrep:
./test.sh '[m]ypgrm'
Difference between pgrep in sh and bash
It's probably a timing issue and pgrep
finds itself, as you're issuing it with -f
and novalidname
is present in the command line. Try with -l
to confirm.
Related Topics
How to Add an Array to Another Array in Ruby and Not End Up With a Multi-Dimensional Result
How to Do Relative Time in Rails
Ruby: What Does the Comment "Frozen_String_Literal: True" Do
How to Understand the Difference Between Class_Eval() and Instance_Eval()
Can't Install Ruby Rvm on Ubuntu 16.04 Due to Gpg Bug
Is This the Best Way to Unescape Unicode Escape Sequences in Ruby
How to Use the Debugger with Ruby 2.0
How to Wait for Process to Finish Using Io.Popen
Can't Install Ruby on Rails with Rvm on Ubuntu 13.04
Popen Getting Pid of Newly Run Process
How to Check If a File Is Being Used by Other Application
How to Distinguish Xlsx and Docx Files from Zip Archives