Why is $$ returning the same id as the parent process?

314,167

Solution 1

$$ is defined to return the process ID of the parent in a subshell; from the man page under "Special Parameters":

$ Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the current shell, not the subshell.

In bash 4, you can get the process ID of the child with BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634

Solution 2

You can use one of the following.

  • $! is the PID of the last backgrounded process.
  • kill -0 $PID checks whether it's still running.
  • $$ is the PID of the current shell.

Solution 3

  1. Parentheses invoke a subshell in Bash. Since it's only a subshell it might have the same PID - depends on implementation.
  2. The C program you invoke is a separate process, which has its own unique PID - doesn't matter if it's in a subshell or not.
  3. $$ is an alias in Bash to the current script PID. See differences between $$ and $BASHPID here, and right above that the additional variable $BASH_SUBSHELL which contains the nesting level.

Solution 4

Try getppid() if you want your C program to print your shell's PID.

Solution 5

this one univesal way to get correct pid

pid=$(cut -d' ' -f4 < /proc/self/stat)

same nice worked for sub

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

check output

pid = 8099
8099 != 8100
Share:
314,167

Related videos on Youtube

ruanhao
Author by

ruanhao

It is funny here.

Updated on May 05, 2022

Comments

  • ruanhao
    ruanhao almost 2 years

    I have problem with Bash, and I don't know why.
    Under shell, I enter:

    echo $$    ## print 2433
    (echo $$)  ## also print 2433
    (./getpid) ## print 2602
    

    Where getpid is a C program to get current pid, like:

       int main() {
        printf("%d", (int)getpid());
        return 0;
       }
    

    What confuses me is that:

    1. I think "(command)" is a sub-process (am i right?), and i think its pid should be different with its parent pid, but they are the same, why...
    2. When I use my program to show pid between parenthesis, the pid it shows is different, is it right?
    3. Is $$ something like macro?

    Can you help me?

    • chepner
      chepner over 10 years
      Note that getpid would show a different process ID even if it weren't run in a subshell.
    • Ben
      Ben over 4 years
      @Marian echo $$ $BASHPID ; ( echo $$ $BASHPID ) demonstrates that it does. Round brackets create a subshell. The statements may change variable values, and the parent shell must not see those changes. This is implemented as a fork() operation.
  • Martin Bouladour
    Martin Bouladour almost 7 years
    "parent" is a bit misleading (at least it was to me), it's actually the "top level" shell. For instance : echo $$; (echo $$; (echo $$)) echoes the same pid three times
  • chepner
    chepner almost 7 years
    Right; I should have said that the value is inherited from a parent shell (which inherited its value from its parent, etc). The top level shell sets it initially, rather than inheriting from its (non-shell) parent process.
  • Alexander Mills
    Alexander Mills almost 5 years
    $ Expands to the process ID of the shell does it tho? echo $ just echoes the literal $.
  • chepner
    chepner almost 5 years
    @AlexanderMills Well, yes; $ alone is not a parameter expansion. The man page is referring to the name of the special parameter, which is $; it's not claiming that $ alone expands.
  • Alexander Mills
    Alexander Mills almost 5 years
    Ok I honestly have no idea what that means, but echo $BASHPID works in bash 4 and 5 (but not version 3.2.57 on MacOS)
  • chepner
    chepner almost 5 years
    All parameter expansions start with $, but $ is also the name of one of the special parameters. $, #, @, *, etc are some of the special parameters; $$, $#, $@, $*, etc are the expressions that expand to the value of each.
  • Martin Dorey
    Martin Dorey over 4 years
    Nice idea, but won't that get you the pid of the fork the shell has run to capture the output of cut? If I run it twice, once with echo $(...) and once without, then I get different answers.
  • Isaac Freeman
    Isaac Freeman over 4 years
    Shouldn't the second bullet be kill -0 $! if we're talking about background processes? PID isn't set to anything by default.
  • joseluisq
    joseluisq over 3 years
    Or if you use Rust just try nix::unistd::getppid() which will get the pid of current processes' parent - docs.rs/nix/0.18.0/nix/unistd/fn.getppid.html