How do you get the PID in bash? |
January 27th, 2014 |
| bash, tech |
bash someone will tell you:
The variable $$ contains the PID.
This is usually correct, but not always. Sometimes it can be
incorrect, but in a way that's actually closer to what you wanted.
The basic problem is that many bash constructs run in a
subshell. This means the shell will fork itself, running your
function in a separate process. This allows simple concurrency, but
it also means a new process id. For example:
$ function a { echo $$; }
$ function b { echo $BASHPID; }
Function a uses $$ while b uses
$BASHPID. When run as normal functions they both give the PID
of bash running them:
$ a
6042
$ b
6042
When run in the background, however, they diverge:
$ a &
6042
$ b &
14774
To run a function in the background bash uses a multiprocess
model, forking a subshell for each one, so we should expect
both a & and b & to give new PIDs. In order to make
this process faster, though, and because POSIX says
so, bash doesn't reinitialize itself when creating a
subshell. This means $$, which was computed once when
bash started, continues to have its original value.
$BASHPID always
looks up the current PID of the executing process, however, so it does
change when you make a subshell.
While this definition of $$ is frustrating if you actually
want to get the current process id, for example to let each background
function have free reign of /tmp/PID, in many cases this
definition is actually helpful. There are many simple constructs in
bash that require subshells, and it's convenient that
$$ stays consistent. For example:
$ ls $SOME_PLACE | while read fname ; do
some_command $fname >> /tmp/$$.output
done
$ other_command /tmp/$$.output
Because pipes run in a subshell if $$ were defined like
$BASHPID all of these some_command outputs would
build up in some random file in /tmp and
other_command would look in a different file. Instead
$$ happens to mean the right thing, and everything works.
Comment via: google plus, facebook, substack