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.

I'm trying to launch a couple of sub-programs from a bash script and then wait on either of them to quit before quitting the other and exiting the script.

CMD1PID=
CMD2PID=

exit_trap () {
    echo "exit trap: killing jobs..." 
    sudo kill $CMD1PID $CMD2PID
    exit
}

set -bm
trap exit_trap EXIT INT TERM

sudo cmd1 --args &
CMD1PID=$?

sudo cmd2 --args &
CMD2PID=$?

wait $CMD1PID $CMD2PID

(For reference, this is GNU bash, version 4.2.37(1)-release (arm-unknown-linux-gnueabi) on Debian Weezy)

Unfortunately, this doesn't seem to work properly. I've tried several variants, such as:

  • using curly braces around the commands and explicitly killing the shell process afterwards, ie { cmd1 --args ; kill -USR1 $$ ; } & or similar, and then trapping on USR1
  • using kill 0 to kill the still-running commands at exit
  • trapping CHLD - this has the disadvantage that I can't sleep between the commands if I need to, which I might eventually need to do.

...but the issues I tend to run into are:

  • Killing one of the commands doesn't cause the parent Bash process to exit and/or kill the other command
  • Killing the parent Bash process doesn't cause both commands to be killed

I suspect that perhaps my requirement to use sudo is tripping me up, as other folks in other scripts seem to be having good luck with similar scripts. Is there a good way of doing what I'm trying to do in bash?

share|improve this question
add comment

1 Answer

You have two problems: You need to identify when any of the interesting children is done, and you need to kill all of them.

The first means you cannot use the "wait" builtin, because that will wait for all children (or all of the listed ones, if any), not for any. Your USR1-based suggestion works well for that (and for EXIT).

The second is much harder: Because you're using sudo, you don't actually have permission to send a signal to the processes; to send a signal to a process, either your userid must match, or you must be root.

You could try to use filesystem- or filehandle-based signaling or something like that, but frankly, that's going to be much more understandable and readable and maintainable in some other scripting language (python, perl, whatever), and even then it's overly complicated. You're probably better off running the entire script under the target user.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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