Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Spawning back ground scripts and checking their return code question 1

Status
Not open for further replies.
Dec 12, 2007
19
0
0
US
I remember that I can spawn another script is back ground by using the

. backgroundscript &

option and then the

wait

statement.

Is there a way I can spawn multiple background scripts and then wait for all of them to finish and be able to check the return code from each?

If so, I would really appreciate a simple example of this, especially the part where I can check the return code from each script.

Thanks in advance
 
Hi

When asking similar questions, is better to specify what shell are you using.
Code:
[gray]# start 10 child processes in background[/gray]
[b]for[/b] i [b]in[/b] `seq [purple]10[/purple]`[teal];[/teal] [b]do[/b] sleep [navy]$i[/navy] [teal]&[/teal] [b]done[/b]

[gray]# wait until all terminates[/gray]
[COLOR=chocolate]wait[/color]
Code:
[gray]# start one child processes in background[/gray]
sleep [purple]10[/purple] [teal]&[/teal]

[gray]# wait until that one terminates[/gray]
[COLOR=chocolate]wait[/color] [navy]$![/navy]

[gray]# display the child's exit code[/gray]
echo [navy]$?[/navy]
Tested with [tt]bash[/tt] and [tt]mksh[/tt].

Note that you can not combine the two usages : if you want the exit code, you have to [tt]wait[/tt] for that explicit job. See the [tt]wait[/tt] shell builtin in your shells man page.

Additionally take a look at the [tt]jobs[/tt] shell builtin, which lists the currently alive and recently terminated background child processes.

Feherke.
 
Feherke said:
Note that you can not combine the two usages

Well, Feherke, I beg to differ:

Code:
sleep 10 &
pid10=$!
sleep 30 &
pid30=$!
sleep 15 &
pid15=$!
(sleep 20;exit 1)&
pid20=$!

wait $pid10
echo rc of sleep 10 is $?

wait $pid30
echo rc of sleep 30 is $?

wait $pid15
echo rc of sleep 15 is $?

wait $pid20
echo rc of sleep 20... is $?

But it does mean a script will need to keep track of all the PIDs of the background jobs it spawns...

HTH,

p5wizard
 
Hi

p5wizard said:
Feherke said:
Note that you can not combine the two usages
Well, Feherke, I beg to differ:
Now I either not understand the expression "beg to differ" or not understand your code. There you not combined the two usages : the [tt]wait[/tt] and the [tt]wait $pid[/tt], so it illustrates exactly what I wrote. ( Or at least what I intended to write... )


Feherke.
 
Hi

Regarding my suggestion to read about the [tt]jobs[/tt] builtin, here is an example of how I would use it :
Bash:
[gray]#!/bin/bash[/gray]

[COLOR=chocolate]set[/color] -m
[COLOR=chocolate]shopt[/color] -s extglob

[navy]notified[/navy][teal]=()[/teal]

[COLOR=darkgoldenrod]function chchld()[/color]
{
  [b]while[/b] [COLOR=chocolate]read[/color] -a job[teal];[/teal] [b]do[/b]
    [navy]id[/navy][teal]=[/teal][green][i]"${job[0]//@([[/i][/green][lime][i]\[\][/i][/lime][green][i]+-])}"[/i][/green]
    [teal][[[/teal] [green][i]"${notified[id]}"[/i][/green] [teal]]][/teal] [teal]&&[/teal] [COLOR=chocolate]continue[/color]
    [COLOR=chocolate]set[/color] - [green][i]"${job[@]}"[/i][/green]
    [b]case[/b] [green][i]"$2"[/i][/green] [b]in[/b]
      [green][i]'Done'[/i][/green][teal])[/teal] [navy]code[/navy][teal]=[/teal][purple]0[/purple][teal];[/teal] [COLOR=chocolate]shift[/color] [purple]2[/purple] [teal];;[/teal]
      [green][i]'Exit'[/i][/green][teal])[/teal] [navy]code[/navy][teal]=[/teal][green][i]"$3"[/i][/green][teal];[/teal] [COLOR=chocolate]shift[/color] [purple]3[/purple] [teal];;[/teal]
      [teal]*)[/teal] [COLOR=chocolate]continue[/color] [teal];;[/teal]
    [b]esac[/b]
    notified[teal][[/teal]id[teal]]=[/teal][green][i]'1'[/i][/green]
    echo [green][i]"rc of $@ is $code"[/i][/green]
  [b]done[/b] [teal]<<<[/teal] [green][i]"$( jobs )"[/i][/green]
}

[COLOR=chocolate]trap[/color] chchld SIGCHLD

sleep [purple]10[/purple] [teal]&[/teal]
sleep [purple]30[/purple] [teal]&[/teal]
sleep [purple]15[/purple] [teal]&[/teal]
[teal]([/teal]sleep [purple]20[/purple][teal];[/teal][COLOR=chocolate]exit[/color] [purple]1[/purple][teal])&[/teal]

[COLOR=chocolate]wait[/color]

echo [green][i]"That's all, folks !"[/i][/green]

[COLOR=chocolate]trap[/color] - SIGCHLD
Tested with [tt]bash[/tt] 4, no chance to run on other shells. This is just an example while waiting for the OP's specification.

Of course, if exit codes not have to be reported ASAP in ( almost ) the order of completion, then p5wizard's code is the solution.


Feherke.
 
... in (almost) the order of completion... ?

Well not exactly... if for some reason the first background job takes the longest time to complete, the first [tt]wait[/tt] will delay the running of the other [tt]wait[/tt]s. But the subsequent [tt]wait[/tt]s will then terminate immediately and report the return codes.

And Feherke, I guess you are right about not being able to combine the two usages, but that I did not grasp the meaning of what you wrote - or what you intended to write... (sorry).


HTH,

p5wizard
 
Hi

p5wizard said:
if for some reason the first background job takes the longest time to complete, the first wait will delay the running of the other waits.
Correct. And that is OK for in most cases, so "then p5wizard's code is the solution".

My code just exemplifies a solution for the few cases when reporting the completion has to be done ASAP. Just to explain why I recommended reading on [tt]jobs[/tt].

[small]( Seems that today I explain myself worst than anytime. Sorry. I better delay further posting for tomorrow. )[/small]

Feherke.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top