I am trying to get the pid of a currently executing subshell - but $$
is only returning the parent pid:
#!/usr/bin/sh x() { echo "I am a subshell x echo 1 and my pid is $$" } y() { echo "I am a subshell y echo 1 and my pid is $$" } echo "I am the parent shell and my pid is $$" x & echo "Just launched x and the pid is $! " y & echo "Just launched y and the pid is $! " wait
Output
I am the parent shell and my pid is 3107 Just launched x and the pid is 3108 I am a subshell x echo 1 and my pid is 3107 Just launched y and the pid is 3109 I am a subshell y echo 1 and my pid is 3107
As you can see above, when I run $$
from the function that I've backgrounded, it does not display the PID as when I do $!
from the parent shell.
There is a special variable called "$" and "$BASHPID" which stores the process ID of the current shell. Go ahead and run the below command to see what is the process ID of your current shell.
A process is nothing but running instance of a program and each process has a unique PID on a Unix-like system. The easiest way to find out if process is running is run ps aux command and grep process name. If you got output along with process name/pid, your process is running.
If you are running bash v4 or better, the PID of the subshell is available in $BASHPID
. For example:
$ echo $$ $BASHPID ; ( echo $$ $BASHPID ) 32326 32326 32326 1519
In the main shell, $BASHPID
is the same as $$
. In the subshell, it is updated to the subshell's PID.
Pre version 4, you need a workaround:
$ echo $$; ( : ; bash -c 'echo $PPID' ) 11364 30279
(Hat tip: kubanczyk)
Notice that, without the colon, the work-around does not work:
$ echo $$; ( bash -c 'echo $PPID' ) 11364 11364
It appears that, in the above, a subshell is never created and hence the second statement returns the main shell's PID. By contrast, if we put two statements inside the parens, the subshell is created and the output is as we expect. This is true even if the other statement is a mere colon, :
. In shell, the :
is a no-operation: it does nothing. It does, in our case however, force the creation of the subshell which is enough to accomplish what we want.
On debian-like systems, dash
is the default shell (/bin/sh
). The PPID
approach works for dash
but with yet another twist:
$ echo $$; ( dash -c 'echo $PPID' ) 5791 5791 $ echo $$; ( : ; dash -c 'echo $PPID' ) 5791 5791 $ echo $$; ( dash -c 'echo $PPID'; : ) 5791 20961
With dash
, placing the :
command before the command is not sufficient but placing it after is.
PPID
is included in the POSIX specification.
mklement0 reports that the following works as is with bash
, dash
, and zsh
but not ksh
:
echo $$; (sh -c 'echo $PPID' && :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With