1

I have a Bash script that starts one web server, does some work, and then starts a second web server. I would like the script to exit, and for both of these servers to be terminated, if either server exits or the user types Ctrl+C.

What I have now looks like this:

start_server_1 &
server_1_pid=$!

trap "kill $server_1_pid" EXIT

# ...do some work that requires server 1 to be running...

start_server_2 || exit $?

This correctly shuts down both servers if the user types Ctrl+C. If Server 1 exits, however, then Server 2 and the script itself continue to run. How can I make sure that both servers and the script will be taken down if one of these processes exits?

2
  • Can you run the servers such that they do not fork? That should make them more trackable by a simple shell script.
    – thrig
    Commented May 24, 2016 at 14:01
  • @thrig I want to run two servers simultaneously from one script, so I assume I need to run at least one of them in the background…
    – bdesham
    Commented May 24, 2016 at 14:49

1 Answer 1

4

Run both processes in the background, then wait -n to wait for one of them to exit.

Bash doesn't report back which process exited, but you can run jobs -p to get the list of background jobs that are still running and kill them.

start_server_1 &
server_1_pid=$!
start_server_2 &
server_2_pid=$!
wait -n
kill $(jobs -p)

wait -n is new in bash 4.3. In older versions, doing this is much more difficult.

Other common shells don't have wait -n, but they instead let you set a trap on SIGCHLD and call plain wait. In dash, ksh93, mksh and zsh, you can write

trap 'kill $server_1_pid $server_2_pid; exit' CHLD
wait

This doesn't work in bash because there the SIGCHLD trap is only invoked after all jobs have finished running.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .