Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question already has an answer here:

Am writing a bash 4.1 script...

  • Would like 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 docsalvage'  && return
  #
  standby  >/dev/null 2>&1  &
  echo $!
}
share|improve this question

marked as duplicate by enzotib, slm, Anthon, jasonwryan, Gilles Sep 11 '13 at 22:59

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
Have you considered the possibility of checking $? 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. –  Michael Kjörling Sep 11 '13 at 13:41
2  
@enzotib Not really. The OP knows about using $! 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:04
    
What do you mean by “if the backround job always starts”? Unless fork 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 unix.stackexchange.com/q/30370, since you know about $!, but your question doesn't make sense: $! is the answer. –  Gilles Sep 11 '13 at 22:58
    
Thanks. You're right in part. Sorry for forgetting this was still hanging without a resolution. I've added the solution implemented to the bottom of the question. –  DocSalvage Jan 16 at 10:56

1 Answer 1

A bit of a hackish workaround:

jobs &>/dev/null
cmd &
new_job_started="$(jobs -n)"
if [ -n "$new_job_started" ];then
    VAR=$!
else
    VAR=
fi

Thanks to @terdon's comment for directing my attention to help jobs.

share|improve this answer
2  
Nice hack, +1. If you just run jobs -p | wc -l once before launching cmd and then once more afterwards and compare the numbers, you can do it even if there are other background jobs. –  terdon Sep 11 '13 at 13:49
1  
Thanks for directing my attention to help jobs. I got an even easier solution. Editing answer... –  Joseph R. Sep 11 '13 at 13:52

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