How to run scripts parallely inside shell script?

Hi ,

I have 4 scripts example script1,script2,script3,script4 .

I have to run script1,script2 and script3 parallely since this 3 scripts dont have dependencies .
Once script1,script2 and script3 got completed successfully , I have to trigger script4.

Can someone help me on this how to right script for this!!!

Thanks,
Vinoth

What have you tried so far?
What scripting langauge?

Hi vinothsekark,

You can try as follows, not tested though.

#!/bin/bash
./script1 &
./script2 &
./script3 &
Q=1
 
While (Q==1)
do
PID1=`ps -ef | grep -v grep | grep "script1"`
PID2=`ps -ef | grep -v grep | grep "script2"`
PID3=`ps -ef | grep -v grep | grep "script3"`
 
 
sleep 10 ## you can give here number of seconds as per you wish as not sure about how long scripts wil be taking to complete##
 
if [[ $PID1 == "" && $PID2 == "" && $PID3 == "" ]]
then
       ./script 4
       Q=0
else
       Q=1
fi
done

kindly try it in a non live environment as it is not tested and let us know.

EDIT: Sorry sea seems we have updated the post on same time didn't see your question.

Thanks,
R. Singh

@ RavinderSingh: No issues.
There is a space and numbering issue with $PID =="" -> $PID3 == ""

1 Like

The same could be achieved with

./script1 &
./script2 &
./script3 &
wait
./script4

However this wil also not test the return codes of the background scripts..
The challenge is to reliably capture those before script 4 can continue...

Something like this perhaps (not tested)

wrong=0
./script1 & ./script2 & ./script3 &
for job in $(jobs -p)
do
  wait $job || wrong=$((wrong+1))
done
if [ $wrong = 0 ]; then
  ./script4
fi
1 Like

The capture whether the script is running or not - is easy, at least when compared to the challenge transporting the exit value out of the subshell to that this handler script knows it, which script has exited with which exit code.

I would have a solution for this at hand, but I'm afraid it works only with 1 background process at a time (that is pseudo-copied to below example).

Either way, it forces you to send a more complex command in the background process, adapt to all 3 files.

( ./script1 ; printf $? > ./script1_ret  )

Then catch the result of those ./script[1-3]_ret files within a loop, and it should be fine.

Hope this helps

EDIT:
Just for the challenge I've written a script, but not going to post until TO has posted his efforts.

Came up with this alternative with bash, ksh93 or zsh, using the named pipes of process substitution.

{
  read rc1 <&3
  read rc2 <&4
  read rc3 <&5
} 3< <(./script1 >/dev/null 2>&1; echo $?) \
  4< <(./script2 >/dev/null 2>&1; echo $?) \
  5< <(./script3 >/dev/null 2>&1; echo $?) 
if [ $rc1 = 0 ] && [ $rc2 = 0 ] && [ $rc3 = 0 ] ; then
  ./script4
fi
1 Like

I didn't have any issues with this approach using bash and ksh:

./script1 & p1=$!
./script2 & p2=$!
./script3 & p3=$!

wait $p1 ; rc1=$?
wait $p2 ; rc2=$?
wait $p3 ; rc3=$?

# Some debug output
printf "Job 1 (%d): %d\n" $p1 $rc1
printf "Job 2 (%d): %d\n" $p2 $rc2
printf "Job 3 (%d): %d\n" $p3 $rc3

if [ $rc1 = 0 ] && [ $rc2 = 0 ] && [ $rc1 = 0 ]
then
    ./script4
fi

Easier with bitwise-or:

./script1 & p1=$!
./script2 & p2=$!
./script3 & p3=$!

# once rc goes non-zero, it stays that way
wait $p1 ; rc=$?
wait $p2 ; rc=$(( $rc | $? ))
wait $p3 ; rc=$(( $rc | $? ))


if [ $rc = 0 ]
then
    ./script4
fi

It's not a big deal for 3 scripts. But if you spawned 30 or so...

You do lose the ability to tell which script failed though.

If you don't care which ones fail, there is no need to keep track of the individual return codes at all:

./script1 & p1=$!
./script2 & p2=$!
./script3 & p3=$!

# Execute script4 only if all other scripts complete successfully:
wait $p1 && wait $p2 && wait $p3 && ./script4
rc=$?

# Wait for remaining children if script1 or script2 failed:
wait
exit $rc

Note that the shell is only required to keep track of CHILD_MAX processes and the standards say CHILD_MAX can be as small as 25. So, if you want to keep track of more than 25 background processes, verify that your shell can keep track of all of them by checking the CHILD_MAX limit on your system with the command:

getconf CHILD_MAX

Also note that if you have CHILD_MAX processes running, attempts to start any more processes (foreground or background) will fail.

@ Scrunitizer: Seriously?
Thats nice and so small.

Guess i like writing 'gui's way too much...
That makes those scripts always so immense :stuck_out_tongue: