MLUG: Re: [MLUG] basic Unix pipe/exit code problem
Re: [MLUG] basic Unix pipe/exit code problem
Email address obfuscation in effect -- please click here to turn it off.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
On Sat, 5 Mar 2005 11:04:37 -0600 (CST), Mike Miller
<EMAIL:PROTECTED> wrote:
> On Sat, 5 Mar 2005, Scott Hussey wrote:
> 
> > On Thu, 3 Mar 2005 12:24:49 -0600, Mark Rages <EMAIL:PROTECTED> wrote:
> >> I have reduced my problem to this:
> >>
> >> ( /bin/false | gzip > /dev/null ) || echo fail
> >>
> >> I want it to echo "fail" because /bin/false gives a nonzero exit code.
> >>  But it doesn't.  What am I missing?
> >
> > Google "PIPESTATUS" or search for it in the bash man page.
> >
> >       PIPESTATUS
> >              An  array  variable (see Arrays below) containing a list of exit
> >              status values from the processes in  the  most-recently-executed
> >              foreground pipeline (which may contain only a single command).
> >
> >
> > Scott-Husseys-Computer:~/dev/html scott$ false | gzip > /dev/null
> > Scott-Husseys-Computer:~/dev/html scott$ echo ${PIPESTATUS[*]}
> > 1 0
> 
> There it is!  So you can do things like this in a script:
> 
> #!/usr/bin/bash
> false | sort | uniq | grep 1 | gzip | > /dev/null
> echo ${PIPESTATUS[*]}
> 
> and it will return this:
> 
> 1 0 0 1 0 0
> 
> Or, Mark could just look at PIPESTATUS[0] to see the exit status of the
> first command in the pipe.  I don't know bash so well, but something like
> this pseudocode:
> 
> if PIPESTATUS[0]==1 then
>    echo "backup failed" | mail mark
> fi
> 
> Would that work?
> 
> Mike

Yes, that would work, but I ended up using subshells like this:

trap 'exit 1' 15

(A || kill $$) | 
   (B || kill $$) | 
          ...

I wrote this Python function to assemble the above sequene for me:

def safe_pipe_system(commands):
    """ constructs a bash system of pipes, where a failure in any pipe will
        result in the system failing.
 
        commands is a list of commands in the order to be piped together.
        return value is a string, ready to pass to os.system() etc.
        """
         
    commands=['']+[command+' || kill $$ ' for command in commands]
 
    return ("trap 'exit 1' 15\n"+
            reduce(lambda a,b: '('+a+b+') | ',
                   commands[:-1])
            +commands[-1])

Regards,
Mark
EMAIL:PROTECTED
--
You think that it is a secret, but it never has been one.
  - fortune cookie
_______________________________________________
members mailing list
EMAIL:PROTECTED
http://mlug.missouri.edu/mailman/listinfo/members