morrin has asked for the wisdom of the Perl Monks concerning the following question:

Hi I have a quick question which is not strictly a "perl" problem. I am forking and exec'ing in a script. The command that I am exec'ing pipes the output from one command to another command. I then wait on the child in the parent and I want to collect the return status of the first process and not the second. Basically, I have something like
if (fork()){ } else { exec "com1 | com2"; }
And I have a signal handler that reaps the child and does a check for $? to get the status. However as expected, it returns the exit status of "com2". Is there any way to do what I want to do? I've tried looking at some other message boards and I think people get around it by playing around with named pipes and echoing each individual exit status back to the shell. What I want is to have the child process return the status of "com1" back to the parent. Is this possible? I'm sure it is possible but is there an elegant solution to it? Thanks in advance for any reply.

Replies are listed 'Best First'.
Re: Returning status to parent from pipe
by ikegami (Patriarch) on Aug 25, 2010 at 20:34 UTC

    Be the shell and do the piping yourself.

    use IPC::Open3 qw( open3 ); local *TO_CHLD; local *PIPE; local *FR_CHLD; my $com1_pid = open3(*TO_CHLD, *PIPE, '>STDERR', 'com1'); my $com2_pid = open3('<PIPE', '*FR_CHLD', '>STDERR', 'com2'); ... waitpid($com1_pid, 0); # $? is com1_pid's status waitpid($com2_pid, 0); # $? is com2_pid's status
      Thanks for the suggestion. However I am trying to figure out how easily I could integrate that into my code. I left out some of the details, but basically I am forking a series of commands which I first predefine. Some have single commands and some are combinations of commands. I can always do a "hack" by breaking up the commands e.g
      job[0] = "com1 | com 2" job[1] = "com3" . . . job[n] = "com100"
      can become
      job[0] = "com1 > tmp.out" job[1] = "cat tmp.out >com2" job[3] = "com3" . . . job[n+1] = "com100"
      Ideally I was trying to find a solution like Crackers2's suggestion where I can do some "magic" on each command to get it to return the first exit code. I will play around with that for a while and see if I can do that
Re: Returning status to parent from pipe
by Crackers2 (Parson) on Aug 25, 2010 at 20:53 UTC

    If you're using the bash shell something like this might work:

    if (fork()){ } else { exec 'com1 | com2; exit $PIPESTATUS[0]'; }

    You can read more about this in the bash manual.

      Thanks for the replies I had read about the PIPESTATUS variable in bash ..... for some reason I thought that a perl exec would always run in 'sh'. It does on my system. Apologies if this is a very basic question, but can I change that so that it does run in a bash shell?
        On my system, /bin/sh runs bash. But you could specify which shell you want.
        exec(bash => (-c => 'com1 | com2; exit $PIPESTATUS[0]'));