user83642
user83642

Reputation: 85

How to run two processes as though they were one in bash?

I've got two commands foo and bar.

foo runs for a long time without stdin or stdout/stderr activity. bar is a client of foo and runs with stdout/stderr but no stdin activity.

I'd like to run them from one shell, being able to kill both with ctrl-c, and to see the output from bar as it occurs.

i.e. something like this sequence

foo & bar kill -9

but without having to manually do the kill - instead it just happens on ctrl-c

is there a way of scripting this?

thanks

Upvotes: 4

Views: 1414

Answers (2)

paxdiablo
paxdiablo

Reputation: 881443

You can set up a bash script to run the programs and use trap to capture the CTRL-C. Then, in the function called by trap, just kill off the programs.

It's been a while since I did this but I think the following illustrates it.

#!/bin/bash
xx() {
    kill -9 $pid1
    kill -9 $pid2
    echo bye
}
trap 'xx' SIGINT
sleep 1000 &
pid1=$!
sleep 2000 &
pid2=$!
sleep 3600

Just run this script and CTRL-C it, you'll find that it kills off the two sleep processes.

Upvotes: 2

lhunath
lhunath

Reputation: 125396

Don't use kill -9.

You want to trap on EXIT, not on INT.

trap 'kill $fooPid $barPid' EXIT
foo & fooPid=$!
bar & barPid=$!
wait

This solution will always make sure to terminate foo and bar, whatever the reason for it exiting (excluding it being SIGKILL'ed).

If you want to avoid keeping PIDs (which has some race condition issues) you can do this instead:

trap 'kill $(jobs -p)' EXIT
foo &
bar &
wait

That's a better (and cleaner!) solution if your script has no other jobs.

Ps: These solutions mean foo and bar can write to your terminal (your script's stdout), but neither can read from stdin. If you need either foo or bar to read from stdin, the solution becomes a bit more complex.

Upvotes: 5

Related Questions