unix shell, getting exit code with piped child

后端 未结 5 474
南旧
南旧 2021-01-18 07:21

Let\'s say I do this in a unix shell

$ some-script.sh | grep mytext

$ echo $?

this will give me the exit code of grep

相关标签:
5条回答
  • 2021-01-18 08:04

    There is a utility named mispipe which is part of the moreutils package.

    It does exactly that: mispipe some-script.sh 'grep mytext'

    0 讨论(0)
  • 2021-01-18 08:10

    If you're using bash:

    PIPESTATUS
        An array variable (see Arrays) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). 
    
    0 讨论(0)
  • 2021-01-18 08:11

    First approach, temporarly save exit status in some file. This cause you must create subshell using braces:

    (your_script.sh.pl.others; echo $? >/tmp/myerr)|\ #subshell with exitcode saving
    grep sh #next piped commands
    exitcode=$(cat /tmp/myerr) #restore saved exitcode
    echo $exitcode  #and print them
    

    another approach presented by Randy above, simplier code implementation:

    some-script.sh | grep mytext
    echo ${PIPESTATUS[0]} #print exitcode for first commands. tables are indexted from 0
    

    its all. both works under bash (i know, bashizm). good luck :) both approaches does not save temporarly pipe to physical file, only exit code.

    0 讨论(0)
  • 2021-01-18 08:15

    There are multiple solutions, it depends on what you want to do exactly.

    The easiest and understandable way would be to send the output to a file, then grep for it after saving the exit code:

    tmpfile=$(mktemp)
    ./some-script.sh > $tmpfile
    retval=$?
    grep mytext $tmpfile
    rm tmpfile
    
    0 讨论(0)
  • 2021-01-18 08:21

    A trick from the comp.unix.shell FAQ (#13) explains how using the pipeline in the Bourne shell should help accomplish what you want:

       You need to use a trick to pass the exit codes to the main
       shell.  You can do it using a pipe(2). Instead of running
       "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
       to the shell.
    
       exec 3>&1
       eval `
         # now, inside the `...`, fd4 goes to the pipe
         # whose other end is read and passed to eval;
         # fd1 is the normal standard output preserved
         # the line before with exec 3>&1
         exec 4>&1 >&3 3>&- 
         {
           cmd1 4>&-; echo "ec1=$?;" >&4
         } | {
           cmd2 4>&-; echo "ec2=$?;" >&4
         } | cmd3
         echo "ec3=$?;" >&4
    
    0 讨论(0)
提交回复
热议问题