[Chicago-talk] Script design question

Leland Johnson easyasy2k at gmail.com
Fri Dec 16 19:53:10 PST 2005

Happy to help. I had no idea I'd be applying knowledge from class  
this quickly.

On Dec 16, 2005, at 4:30 PM, Young, Darren wrote:

>> if( ($pid2 = fork()) == 0 ) {
>>      print "child 2 execs `date`\n";
>>      exec("date") or die "error executing `date`!\n";
>>      # exec never returns on success
> At this point in the example, using system() wouldn't be a good idea
> since it does a fork() itself correct


> Also, how can I deal with grabbing stdout and stderr from what exec()
> produced? Should I just dup those at the beginning of the script to a
> logfile as in:
>     open( STDOUT, ">>$LOGFILE" ) or die "Unable to dup STDOUT: ($!) 
> \n";
>     open( STDIN,  "/dev/null" )  or die "Can't read /dev/null: ($!)";
>     open( STDERR, ">>&STDOUT" )  or die "Can't dup stdout: ($!)";

Yep. I'd dup everything to different files in the child processes  
(fork() == 0) though. You'd probably want each process writing to a  
different log file, since they could write lines in any order. Also,  
using the three argument version of open is almost always a good idea.

> What if a the command exec()'d exits with values other than just  
> true or
> false?

exec() does not return, unless it fails to execute the command (*not*  
the command fails). If exec() works, that perl process is overwritten  
(in memory) with the new process, so no more code in that particular  
perl process is run.

> How could that be reached and passed upstream?

You could potentially exit with some odd status code if exec() fails  
can catch that in the while(waitpid...) loop.

> In your example,
> you examined $? in the while($kid) loop, is the '$? / 256' the return
> value from the exec() call or the command that exec() in fact  
> executed?

$? is "The status returned by the last...successful call to wait() or  
waitpid()... Thus, the exit value of the subprocess is really ("$? >>  
8")". (perlvar) Basically a direct interface to the C call - except C  
has lots of macros to easily dissect it.

The return value meaning the status of the program that waitpid() was  
waiting on (what exec() executed or the perl process that failed to  
exec() - they have the same pid).

> If it is in fact the return from the exec()'d command, is that because
> you have no explicit exit() in that portion and $? is set to the value
> of the last expression (like what happens at the end of a sub)?

$? wouldn't be set since exec() doesn't make a child process, or do  
anything else that would change it (see perlvar).

> The perldoc for exec() says: "It fails and returns false only if the
> command does not exist and it is executed directly instead of via your
> system's command shell"
> So, it seems that exec() returns false *only* when that particular
> condition is met. So if I tried to exec('/foo/bar/cmd') and it doesn't
> exist, it will come back false. If however, /foo/bar/cmd returns  
> say, 32
> exec() still comes back with true. Reason I ask is that I know some of
> the iPlanet utilities have return codes other than 0 or 1 that  
> indicate
> "transient" error conditions.

exec() doesn't return. $?/256 will hold the return codes of the $kid  
child process that just completed/exited/whatever in the while 
(waitpid...) loop.

> What if I used something like open3 inside the fork() to obtain access
> to STDIN, STDOUT and STDERR individually? Doesn't sound like a good  
> idea
> to me, but I've never tried it.

Looks complicated. I haven't used it either. Using sysread is  
definitely complicated. I would really avoid this unless the launcher  
really had to know the output of the log files as its written.  
There's probably an easier way to do that anyways (named pipe on file  
system for log files?).

Leland Johnson

More information about the Chicago-talk mailing list