(Former Title - bash: Run command in background and capture pid)
NOTE This is not a [DUPLICATE] of the other question since it addresses the unexpected behavior of bash where a failure of the subprocess to start, say due to 'command not found', can leave
$!
set to the pid of the calling process instead of the pid of the failed subprocess or "" (null). -- docsalvager
I'm writing a bash 4.1 script...
- Would like to run another script (or internal function) in the background...
- And capture the pid of that background job in a variable in the foreground script...
- If the job doesn't start, the variable should get a null (i.e. "").
Either of these work if the backround job always starts...
cmd &
VAR=$!
or...
( cmd & ); VAR=$!
If cmd
runs, the pid of the last command started ($!) will be the one we want and $VAR will be correct.
However, if cmd
doesn't start, $VAR will the the pid of the last command before that that started which could be the pid of the foreground script itself. Since I need the pid of cmd
for the purpose of killing the process under certain conditions later on, possibly getting the wrong pid just won't do.
What I really need is for VAR to only be changed if the background job ran. Something like the syntactically incorrect...
VAR=
( cmd & ); && VAR=$!
Implemented Solution
The comments and Joseph R's answer have been very helpful. For the benefit of anyone with a similar problem...
The following bash function runs the GtkDialog standby
script in the background. Being inside a function, which itself is run in a subprocess, seems to provide the isolation I need to avoid getting the PID of the calling script instead of the PID of the standby
script if standby
fails...
function standbyBg () {
ifHelpShow "$1" 'standbyBg
Run standby (busy "throbber") in background and echo its pid.
Example:
standbyPID=$(standbyBg)
Revised:
20131123 docsalvager' && return
#
standby >/dev/null 2>&1 &
echo $!
}
$?
before assigning from$!
? I have no idea if it'll work, but if it does then it might help with only assigning VAR if the command invocation is successful. – user Sep 11 '13 at 13:41$!
to capture the last command's PID. They want to make sure the backgrounded command was actually started so that$!
doesn't capture the PID of an earlier command. – Joseph R. Sep 11 '13 at 19:04fork
fails due to a lack of resources, the background job always starts in your code snippet. Even if the job consists solely of some external command that does not start, the job is still started and$!
is set. Please post your actual problem, including steps to reproduce it. P.S. I voted to close as “unclear”: this isn't really a duplicate of http://unix.stackexchange.com/q/30370, since you know about$!
, but your question doesn't make sense:$!
is the answer. – Gilles 'SO- stop being evil' Sep 11 '13 at 22:58export PID_FILE=$(mktemp /tmp/standby.XXXXXXXXXXXXXXX); (tfile=$PID_FILE; ./standby& s_pid=$!; echo $s_pid > $tfile; wait; rm $tfile;)& sleep 0.1; if [ -r $PID_FILE ] ; then S_PID=$(cat $PID_FILE); else S_PID=""; fi ; echo pid $S_PID; unset PID_FILE
– gam3 Sep 04 '16 at 07:42