Wait for one of two processes to complete in a shell script
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Wait for one of two processes to complete in a shell script
Title says it all pretty much. Let's say I start process A, then start process B. How can I wait until either A or B completes (without waiting for both to complete), and then continue execution of my script?
Maybe I didn't explain my problem clearly in my first post. I launch two processes, A and B. If A finishes before B, I want my script to resume as soon as A finishes. If B finishes before A, I want my script to resume as soon as B finishes.
You could always exploit SIGCHLD. Here is one way to do so (there are many others in a similar fashion).
Code:
#!/bin/sh
echo "Starting both processes…"
sh -c 'trap "exit" CHLD
process1 & process2 & wait'
echo "One process has exited."
Edit:
It seems that the above will not work if sh is symlinked to bash. It will work on ksh, zsh, dash, etc., but for some reason, trapping SIGCHLD doesn’t work in bash in a script.
As a workaround (if sh is a symlink to bash on your system), try this:
Code:
#!/bin/sh
echo "Starting both processes…"
sh -c 'set -m
trap "exit" CHLD
process1 & process2 & wait'
echo "One process has exited."
I ask because I assume that "either ... or ..." in your OP means what it says, whereas to me the logic in both post #4 & #6 seems to be AND logic.
I interpreted the question as “either … or …” and my post logic reflects this. I am not sure how you read otherwise. The line “One process has exited.” will be printed when either process exits.
Btw, AND logic is much easier to do (at least in shell), since the wait builtin may take multiple pid or job-id arguments, and will wait for all of them.
It was either or. I'm automating a series of tasks, keeping two running at a time (to make better use of a dual-core processor). So, as soon as one task finishes, another should start. Since the tasks vary in length, I'm arranging it like a queue where each 'slot' takes a new task of a list when its current process has finished.
I'm automating a series of tasks, keeping two running at a time (to make better use of a dual-core processor). So, as soon as one task finishes, another should start. Since the tasks vary in length, I'm arranging it like a queue where each 'slot' takes a new task of a list when its current process has finished.
You can do this using SIGCHLD as well (although it would be much easier in C).
Try out the following (it should do what you want, barring race conditions):
Code:
#!/bin/bash
SLOTS=2
( set -m
trap "if read next ; then
eval \$next &
fi" CHLD
for ((i = 0; i < $SLOTS; i++)); do
read proc
eval "$proc" &
done
wait
) << __EOF__
zenity --info --text=1st
zenity --info --text=2nd
zenity --info --text=3rd
zenity --info --text=4th
zenity --info --text=5th
zenity --info --text=6th
__EOF__
echo "Rest of script goes here"
I am not sure, however, of the portability to other shells.
When you say queue, generally you mean a First-In, First-Out (FIFO), so you could very well use pipes (named or anonymous) instead of hardcoding as the method of sending commands.
Last edited by osor; 06-10-2008 at 04:10 PM.
Reason: remove race condition
I haven’t been here for awhile, but if anyone is still interested, I fixed the race condition in the above script. Basically, it involves setting up the SIGCHLD handler first, and then ensuring there are no calls to external programs (except those you have on queue). So that means instead of using seq(…), you have to use a counter.
I have edited the above accordingly, and it works (for me) on bash and zsh.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.