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?

  • Can you run the servers such that they do not fork? That should make them more trackable by a simple shell script. – thrig May 24 '16 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 May 24 '16 at 14:49
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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