Richard Hu
Richard Hu

Reputation: 891

Shell: how to run two scripts A and B in parallel and stop B when A is over

Suppose I have a shell script A.sh whose content is:

sleep 2
echo "A: 2s"
sleep 2
echo "A: 4s"
sleep 2
echo "A: 6s"

I also have a shell script B.sh whose content is:

sleep 2
echo "B: 2s"
sleep 2
echo "B: 4s"
sleep 2
echo "B: 6s"
sleep 2
echo "B: 8s"
sleep 2
echo "B: 10s"

When I hope to run A and B in parallel, I created a script C.sh whose content is:

sh A.sh &
sh B.sh &
wait

The output is:

B: 2s
A: 2s
A: 4s
B: 4s
A: 6s
B: 6s
B: 8s
B: 10s

In this way A and B can run in parallel. Now I have one more requirement that is I hope to stop B when A is over. I followed the steps mentioned here and modified C.sh to:

parallel -j2 --halt now,success=1 ::: 'sh A.sh' 'sh B.sh'

The output is:

A: 2s
A: 4s
A: 6s
parallel: This job succeeded:
sh A.sh

It seems B is not running in this way. Can anyone advise me what is the correct way to run two scripts A and B in parallel and stop B when A is over?

Upvotes: 1

Views: 107

Answers (3)

William Pursell
William Pursell

Reputation: 212198

If you're using a sufficiently modern bash (eg, this does not work in 3.2.5.7, but it does in 5.0.16, so it was introduced sometime between those), you can do:

a.sh &
b.sh &
wait -n
kill -- -$$

This waits until either process terminates and then sends a SIGTERM to all the jobs in the process group. Note, this will send the SIGTERM to all processes in the group, including the main script, so you may need to handle that. If you want to restrict the jobs to which the signal is sent, run them in their own process group and send the signal appropriately.

Upvotes: 0

Mark Setchell
Mark Setchell

Reputation: 207375

I think it is running, but output is grouped by job by default, so you won't see the output from B till A is finished but when A finishes, the whole GNU Parallel process exits.

Try switching to line-buffered output:

parallel --linebuffer sh ::: [AB].sh

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 140900

to run two scripts A and B in parallel and stop B when A is over?

So do just that.

sh B.sh &
b_pid=$!
{
    sh A.sh 
    kill "$b_pid"
} &
wait

Upvotes: 5

Related Questions