3

I am trying to understand the "oneliner" in this comment by @sysfault:

/bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &

I tried the following variations...

Different $$ inside and out:

/bin/bash -c 'echo $$ && exec sleep 5' ; echo $$
14408
29700

Same pid (but in background):

$ /bin/bash -c 'echo $$ && exec sleep 5' & echo $! 
[1] 8309
8309
$ 8309

[ 1 ]+  Done  /bin/bash -c 'echo $$ && exec sleep 5'

Different pid for $$ & $! :

/bin/bash -c 'echo $$ && exec sleep 5 & echo $!'                                 
6504
6503

Kill did not work: /bin/bash -c 'echo $$ && (sleep 15 ; echo done)'
19063 Killed $ done (echo showed up after the kill)

Same pid with access to the pid of the foreground process:

$ /bin/bash -c 'echo > tmp.pid ; sleep 10 ; echo $$ ; echo done ; echo $$;'      
28415 (instantly)
28415 (10 seconds later)
done
28415
$ cat tmp.pid 
28415

With this command I was able to kill the pid in another window before the sleep finished - preventing the last three echos from happening:

$ /bin/bash -c 'echo $$ ; sleep 30 ; echo $$ ; echo done ; echo $$;'               
23236
Killed

Context: Ultimately I want to start bash processes via php exec(), and wait for the result before continuing and save the pid so i can clean up in case the manual cancel button is pressed. There are 2 expensive processes i will deal with: one rsync and one git commit & push.

What is the best way to reliably get the pid of a foreground bash script that includes multiple commands (with ; > | or &&) ?

  • Consider using proc_open(), proc_get_status() and proc_close() instead. – Michael Hampton Feb 6 '18 at 20:46
  • This comment was really helpful for the php part of the question, Thanks! I consider to make a separate question rather than get this one moved as @glenn-jackman suggested. – gotjosh Feb 10 '18 at 13:04
5

$$ is the PID of the current shell. When you use $$ in the bash -c script body, you get the pid of that spawned shell

$ echo $$; bash -c 'echo $$'; echo $$
6872
6987
6872

$! is the PID of the last backgrounded process

$ sleep 5 & echo $!; sleep 5 & echo $!; echo ===; pgrep -l sleep
[1] 7118
7118
[2] 7119
7119
===
7118 sleep
7119 sleep

When you do bash -c 'echo $$' & echo $!, you get the same pid printed twice because, for your current shell, $! is the pid of the backgrounded bash process, and inside the script body, $$ is the current pid of that same backgrounded bash process.

When you do /bin/bash -c 'echo $$ && exec sleep 5 & echo $!', you get two different pids: $$ is the pid of the bash process and $! is the pid of the sleep process.

  • I find this odd because you're using exec so it should be the same PID (the sleep process replacing the bash process)
  • However you're using exec ... & so bash must first fork a subshell to run the backgrounded task, and then exec replaces that subshell with sleep.

The answer to your actual question is best answered by a php person, which I am not. You should flag this question to a moderator and request it be moved to Stack Overflow where more php people are bound to hang out.

  • I consider to post a separate question, but I posted this one here consciously, as I want to more deeply understand the details that you outlined. So, Thanks! – gotjosh Feb 10 '18 at 13:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.