Get pid of current subshell

bash, sh

Solution

Modern bash

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.

Old bash (Version 3.x or Earlier)

Pre version 4, you need a workaround:

$ echo $$; ( : ; bash -c 'echo $PPID' )
11364
30279

(Hat tip: kubanczyk)

Why the colon?

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.

Dash

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.

POSIX

`PPID` is included in the POSIX specification.

Portability

mklement0 reports that the following works as is with `bash`, `dash`, and `zsh` but not `ksh`:

echo $$; (sh -c 'echo $PPID' && :)

Problem

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.

Original source

Related problems