Shell pipe: Exit immediately when one command fails

前端 未结 5 882
长发绾君心
长发绾君心 2020-12-28 15:09

I\'m using a pipe of several commands in bash. Is there a way of configuring bash to terminate all commands in the whole pipeline immediately should one of the commands fail

5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-28 15:49

    The following code seems to work by Dash, but EXIT traps within pipe do not work in Bash; maybe it is a bug in Bash.

    #!/bin/sh
    
    echo PID of the shell: $$
    
    trap 'echo In INT trap >&2; trap - EXIT INT; kill -s INT $$' INT
    
    (
        # now in subshell
        pidofsubshell=$(exec sh -c 'echo "$PPID"')
        # $BASHPID can be used as a value, when using Bash
        echo PID of subshell: $pidofsubshell
    
        fifo=$(mktemp -u); shells=$(mktemp) childs=$(mktemp)
        mkfifo $fifo
        trap 'echo In sub trap >&2; rm $fifo $shells $childs; trap - EXIT; exit' EXIT HUP TERM INT ALRM
    
        pipe_trap() {
            code=$?
            echo In sub sub trap $1 >&2
            echo $1 $code >> $fifo
        }
        { trap 'echo In pipe signal trap >&2; kill $(cat $childs $shells) 2>/dev/null' INT HUP TERM ALRM
            { trap 'pipe_trap 1' EXIT
                sleep 30; } \
            | { trap 'pipe_trap 2' EXIT
                sleep 50 & sleep 2; } \
            | { trap 'pipe_trap 3' EXIT
                sleep 40; } &
        }
    
        echo ps tail:
        ps xao pid,ppid,pgid,sid,command | head -n 1
        ps xao pid,ppid,pgid,sid,command | tail -n 15
            ps -o pid= --ppid $pidofsubshell | head -n -2 > $shells # strip pids of ps and head
        echo shells:
        cat $shells
            while read -r ppid; do ps -o pid= --ppid $ppid; done <$shells >$childs
        echo childs of above
        cat $childs
    
        { 
            IFS=' ' read -r id exitcode
            echo Pipe part nr. $id terminated first with code $exitcode\; killing the remaining processes.
            kill $(cat $childs $shells) 2>/dev/null
        } < $fifo
    )
    
    echo
    echo After subshell:
    ps xao pid,ppid,pgid,sid,command | head -n 1
    ps xao pid,ppid,pgid,sid,command | tail -n 15
    

提交回复
热议问题