代码之家  ›  专栏  ›  技术社区  ›  dariober

从命名管道捕获非零退出代码

  •  2
  • dariober  · 技术社区  · 6 年前

    下面的玩具剧本( tmp.sh )即使发送到命名管道的进程失败,也将退出,并返回代码0。如何从命名管道捕获非零退出代码?一般来说,事实是 某物 出了问题吗?

    #!/bin/bash
    
    set -eo pipefail
    
    mkfifo mypipe
    FOOBAR > mypipe &
    
    cat mypipe
    

    运行并检查退出代码:

    bash tmp.sh
    tmp.sh: line 6: FOOBAR: command not found
    
    echo $? # <- Exit code is 0 despite the "command not found"!
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   anubhava    6 年前

    您需要捕获后台进程的进程ID和 wait 要设置正确的退出状态:

    #!/bin/bash
    set -eo pipefail
    
    rm -f mypipe
    mkfifo mypipe
    
    FOOBAR > mypipe &
    # store process id of above process into pid
    pid=$!
    
    cat mypipe
    
    # wait for background process to complete
    wait $pid
    

    现在,当您运行它时:

    bash tmp.sh
    tmp.sh: line 6: FOOBAR: command not found
    echo $?
    127
    
        2
  •  1
  •   Paul Hodges    6 年前

    如果您需要能够捕捉错误并应用特定的行为,陷阱可能是您的朋友。这段代码会自动打印,所以我在这里发布了一个运行:

    $: tst
    + trap 'x=$?; echo "$x@$0:$LINENO"; exit $x' err
    + rm -f mypipe
    + mkfifo mypipe
    + pid=6404
    + cat mypipe
    + cat ./tst
    #! /bin/env bash
    
    set -x
    
    trap 'x=$?; echo "$x@$0:$LINENO"; exit $x' err
    #set -eo pipefail
    
    rm -f mypipe
    mkfifo mypipe
    
    cat $0 >mypipe &
    pid=$!
    cat mypipe
    wait $pid
    
    fubar >mypipe &
    pid=$!
    cat mypipe
    wait $pid
    
    echo done
    
    + wait 6404
    + pid=7884
    + cat mypipe
    + fubar
    ./tst: line 16: fubar: command not found
    + wait 7884
    ++ x=127
    ++ echo 127@./tst:19
    127@./tst:19
    

    注意 trap 'x=$?; echo "$x@$0:$LINENO"; exit $x' err 线。 它将x设置为最后一个错误代码,这将是触发它的任何代码。然后它打印代码、文件名和当前正在执行的行号(在陷阱之前),并使用错误代码退出程序。这实际上触发了 wait . 它会使它在底部继续回声之前脱落。

    无论有没有 set -eo pipefail .