Difference between pgrep in sh and bash

2019-05-07 10:27发布

问题:

Here is a test:

$ bash -c "pgrep -f novalidname"
$ sh -c "pgrep -f novalidname"
11202

Why is pgrep giving output when run from sh? (As far as I can see, there are no processes on my computer that is named novalidname)

回答1:

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.



回答2:

The actual explanation:

  1. Regardless of flags, pgrep never returns its own PID.

  2. If you execute bash -c with a simple command, then bash will exec the command rather than creating a redundant subshell to execute it in. Consequently, bash -c "pgrep -f blah" will replace the bash process with a pgrep process. If that pgrep process is the only process whose command line includes blah, then pgrep will not display any PIDs (as per 1).

  3. dash does not perform the above optimization. (zsh and ksh do.) So if on your system, sh is implemented with dash, then sh -c "pgrep -f blah" will result in two processes being executed -- the sh process and the pgrep child -- both of which contain blah in their command lines. pgrep will not report itself, but it will report its parent.



回答3:

That's one thing (finding itself because of delay) see also:

$ ps ax | grep novalidname

Here it usually shows as well. (on Ubuntu does for me. (under bash)

The other thing is what is /bin/sh bound to?

On most Linux distros /bin/sh is a soft link to default shell which is usually actually bash, but can be any other shell.

The time difference that causes grep/pgrep to show itself may be introduced by finding a soft link location (hm, odd) or some other shell is bound to /bin/sh which executes slightly different than bash, thus causing the delay needed for process to show in pgrep.

Also, bash will firstly try to source ~/.bashrc and load its history, while /bin/sh will do what will do. In .bashrc can be pgrep defined as alias in another way which may also affect the difference.

To see where /bin/sh points to do:

$ readlink -e /bin/sh

Or just run sh to see what will show up. :D



标签: bash grep sh