Making bash script WAIT after starting subshell
First post - great site. I hope you can help.
Below is a snippet of code from a bash shell script I'm developing to plot some charts (with gradsdap). I used to loop through my text file of locations plotting each chart one at a time, then discovered the power of being able to spawn multiple instances (subshells) of plotting by adding an & at the end of the line. This speeds up the plots by a factor of 5. Excellent! However I'm having trouble getting the script to WAIT for all the child processes to finish before carrying on. I've tried "wait" and also wait for the child processID, but whatever the script seems to run on - echoing "finished meteograms" straight away. I thought just putting "wait" would have the desired effect, but I must be missing something more subtle - or obvious! Any thoughts? Thanks ... if [ $downloadready ] ;then filein="/home/burn/grads_etc/locslatlong.txt" grep '[a-zA-Z]' $filein | awk '{print $1" "$2" "$3}' | while read lat lon location do (gradsdap -bpcx "/home/burn/lib/meteogram_single $today $dt $lat $lon $location" | tail -c+16) & # metgramppid=$! done # wait $metgramppid # wait # really want the script to stop here until all the #+ subshells started above are done. echo finished meteograms? # this pops up right away - hmm # next command.... fi ... |
If I understand you correctly, you want to wait until the multiple "gradsdap" processes complete before continuing with the script. If so, why not do a `ps` and look to see if all the `gradsdap` commands have completed. Once they have (e.g. they are no longer in a `ps` listing) then you continue.
While running a loop to check if the `gradsdap` processes are alive, put in a sleep in the loop to check every 30secs or so. |
Quote:
Code:
if [ $downloadready ] ;then |
Quote:
|
I have the following alias on all of my servers for use which with very little modification could work for you ...
Code:
watch_me(){ while ps -ef | grep $1 | grep -v grep > /dev/null Code:
while ps -ef | grep gradsdap | grep -v grep > /dev/null This is assuming that you are the only person on this box. If someone else uses it, then if they run gradsdap, then your script would wait until any process that they are running finishes as well. If that is the case, then add in another grep for your username as well, and then it would watch for when all of your gradsdap processes have finished, and it wouldn't worry about processes by other users. |
I think you'll find the 'while' loop creates a sub-shell that then creates backgrounded process.
'wait' only waits for procs backgrounded from the 'current' shell. Replace 'while' with a 'for' loop and you should be good. |
Quote:
Code:
#!/bin/bash Code:
~/tmp$ ./wait.sh Code:
#!/bin/bash Code:
~/tmp$ ./wait.sh Code:
#!/bin/sh |
ntubski and chrism01 - I think you've nailed my problem. When running from a pipe, the while loop was starting in a subshell itself, then the wait command wouldn't work for all the other sub-sub-shells.
Thanks to all though - you inspired me to work out the same conclusions myself as well as gaining some other tips as always. http://mywiki.wooledge.org/BashFAQ/024 gives some more background about this. Cheers |
Quote:
"Each command in a pipeline is executed as a separate process (i.e., in a subshell)."When I created my "simple test script", I used a "for" loop instead of the "| while" syntax. So my script was not equivalent. I like ntubski's answer. |
I encountered this post searching for solution to my problem similar to the one described here.
Thanks ntubski for the explanation, that pipe starts a new sub-shell. Great site!!!!!! |
All times are GMT -5. The time now is 10:11 PM. |