Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Perl wait vs Unix ksh wait

by mifflin (Curate)
on Oct 31, 2007 at 17:40 UTC ( #648312=perlquestion: print w/replies, xml ) Need Help??
mifflin has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to convert a ksh script to perl. This script executes some other commands in background and does a wait for all of them do finish and then continues like this...
command1 & command2 & command3 & wait # wait for commands 1-3 to finish
I'm trying to figure out how to do this in perl. Something like ...
system("command1 &"); system("command2 &"); system("command3 &"); wait; # doesn't behave like the unix wait :(
What do I put in place of the perl wait command to get the same behavior as the unix wait when used in a ksh?

Replies are listed 'Best First'.
Re: Perl wait vs Unix ksh wait
by Fletch (Chancellor) on Oct 31, 2007 at 18:32 UTC

    Erm . . . since you're already using the shell to do job control rather than doing fork/exec yourself and since you're not on Wintendo you have a perfectly good shell with job control built in already why not just have the shell do the wait for you?

    system( qq{ command1 & command2 & command3 & wait } );
Re: Perl wait vs Unix ksh wait (spawn)
by tye (Sage) on Oct 31, 2007 at 17:57 UTC

    Well, on a Real™ operating system, you could replace that with:

    my %child; for my $cmd ( "command1", "command2", "command3" ) { $child{system(1,$cmd)}= $cmd; } while( %child ) { my $cmd= delete $child{wait()}; warn "$cmd failed: $?\n" if 0 != $?; }

    But if you are stuck on Unix, then it becomes much harder to "spawn" properly, unfortunately. I'll see if I can write up the helper function for that, but I suspect somebody else will beat me to it.

    - tye        

      Okay, a close approximation to system(1,...) for less fortunate builds of Perl is:

      sub spawn { my( $cmd )= @_; die "Usage: spawn($cmdLine) or spawn([$cmd,@args])" if 1 != @_; die "You don't need this; use system(1,...) instead." if $^O =~ /win32/i; # Not an accurate test my $cpid= fork(); die "Can't fork: $!\n"; if ! defined $cpid; return $cpid if $cpid; if( ! ref $cmd ) { exec( $cmd ); } elsif( 1 == @$cmd ) { $cmd= $cmd->[0]; exec( $cmd $cmd ); } else { exec( @$cmd ); } die "exec failed: $!\n"; }

      But note that system(1,...) has some non-trivial advantages still; I didn't replicate the "pipe to child process for making 'exec fails' cases" saner.

      So you can use spawn($cmd) in place of system(1,$cmd) in the code I provided in the previous node. I didn't write spawn() to handle Win32 because it was a quick hack.

      - tye        

      That seems like a perl limitation, not a unix one, since there are plenty of ways to do this in perl and without.

      For whatever reason, you have to use fork or modules (like IPC::Open3 or whatever) in unix. Actually, why does system(1,$cmd) work at all? I don't see that documented. It's possible I'm blind. I'm cutting down on coffee.

      UPDATE: I still don't see how that's a unix problem, rather than a perl one; but I guess I understand your animosity/reciprocity.

      UPDATE2 (nov 1st): Your example (in a sibling post) also seems intentionally complex...


        Sorry, it is long-standing tradition that, whenever anyone asks a question where the answer in Win32 is harder than the answer in Unix, for several Unix lovers to make jokes about "get a Real™ operating system". I assumed, based on the Golden Rule, that they must want this same treatment when the situation is reversed. However, it appears to often result in several Unix lovers getting their panties in a wad when it is pointed out that their favorite operating system is not perfect, in fact, in some ways inferior to some other operating system (especially if that operating system is from a particular vendor, it seems).

        Oh well, not everybody has a sense of humor about all subjects.

        In my experience, the use of fork or some module will be quite a bit more complex than what I wrote and is likely to be buggy (and is very unlikely to do the nice stuff system(1,...) does with the pipe to the child so the parent can distinguish 'exec' failing from the launched program failing).

        Update: Note that I don't replicate the childish part of the tradition of mispelling the name of the operating system to make fun of it. (:

        - tye        

Re: Perl wait vs Unix ksh wait
by tuxz0r (Pilgrim) on Oct 31, 2007 at 18:25 UTC
    But, if you are "stuck" on Unix (which is really a good thing), you can refer to this node (or many others if you search for fork, exec and wait). Basically, you will fork off each independent process, collecting their process ids and then have the parent script wait until it receives a SIGCHLD from each one signaling it has finished.

    echo S 1 [ Y V U | perl -ane 'print reverse map { $_ = chr(ord($_)-1) } @F;'

      The node you linked to doesn't properly handle fork failing. That is typical.

      See my reply in this thread for a solution that does handle fork failing and for more information about how it still isn't as nice as system(1,...).

      - tye        

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://648312]
Approved by jettero
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2017-01-21 09:09 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (183 votes). Check out past polls.