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 &&) ?

2
  • 1
    Consider using proc_open(), proc_get_status() and proc_close() instead. Commented Feb 6, 2018 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. Commented Feb 10, 2018 at 13:04

1 Answer 1

7

$$ 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.

1
  • 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! Commented Feb 10, 2018 at 13:06

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.