How to implement 'set -o pipefail' in a POSIX way - almost done, expert help needed

后端 未结 4 1852
后悔当初
后悔当初 2021-02-14 22:59

I have to implement the BASH set -o pipefail option in a POSIX way so that it works on various LINUX/UNIX flavors. To explain a bit, this option enables the user to

相关标签:
4条回答
  • 2021-02-14 23:30

    My two cents:

    #!/bin/sh
    
    # Saving the pid of the main shell is required,
    # as each element of the pipe is a subshell.
    self=$$
    
    lots_and_fail() {
        seq 100
        return 1
    }
    
    { lots_and_fail || kill $self; } | sed s/7/3/
    

    This thing seems to do the job. Thoughts?

    0 讨论(0)
  • 2021-02-14 23:37

    When you type:

    run echo "test" ; grep "test" \| awk '{print}'
    

    you invoke run with the arguments echo and "test"; then you invoke grep with arguments "test", |, awk and {print}. Typically, grep is not going to find any of the files called |, awk or {print}.

    To invoke run as you wanted, you'd have to escape the semi-colon like you did the | (and you'd need to do things similarly for && or || or & and possibly other components of a command line; the handling of $(...) or backticks `...` needs to be thought about carefully).

    If you write:

    run echo "test" \; grep "test" \| awk '{print}'
    

    you will at least get all the arguments you intended to run. Whether it then works is debatable; I don't yet understand how the run code you showed is supposed to work.

    [...Later...]

    It does some fearsome I/O redirections, but wraps each segment of a command separated by a pipe symbol into a separate little packet of hieroglyphs. It assumes that wrapping double quotes around an argument neutralizes it correctly, which is not always true (though it is true a lot of the time).

    0 讨论(0)
  • 2021-02-14 23:46

    Am I missing something?

    my-script.sh

    #!/bin/sh
    
    set -e
    
    cat app.log | grep 'ERROR' 
    
    printf 'It will never print this.\n'
    
    $ ./my-script.sh
    cat: app.log: No such file or directory
    
    0 讨论(0)
  • 2021-02-14 23:47

    The core of your idea should probably involve something like this:

    { cmd1 ; echo $? > status1 ; } | cmd2 && grep -q '^0$' status1 }
    

    In longer form, that would be:

    { cmd1 ; echo $? > status1 ; } |  \
    { cmd2 ; echo $? > status2 ; } |  \
      # ... and so on                 \
      cmdN                         && \
      # ^ note lack of wrapper        \ 
    grep -q '^0$' status1 &&          \
    grep -q '^0$' status2 &&          \
      # ... and so on, to N-1
    
    0 讨论(0)
提交回复
热议问题