尝试/捕获的Bash模拟不能按预期工作

时间:2015-03-29 12:43:23

标签: bash shell error-handling

以下switch语句有奇怪的行为:

3)
        if [ $state -ne $last_state ]
        then
            echo "state: $state"
        fi

        stty -F $SERIAL $BAUD -echo igncr
        echo "befor cat"
        {
            cat -v $SERIAL >> $USBDRIVE/gpsData_$filecounter.txt && echo "after cat"
        } || {
            echo "catch"
            state=0
            last_state=3
            ((filecounter++))
        }           
        ;;

我想,当cat命令失败时,如果被命中,“cat after”将被写入,而不是||之后的部分将被罚款。但是当我查看输出时,似乎在回显“cat after”之后发生了中断,以便实际状态不会改变并且将再次输入。然后stty也失败了(因为缺少串行适配器)。之后,cat命令在开始时失败,但现在进入“catch”块......

以下是相关输出:

pi@rpi ~/serial_logger $ ./serial_logger.sh
serial adapter found: ttyUSB0
state: 1
USB-Storage found: usb0
state: 3
before cat
after cat    #here should be entered state 0
state: 3
stty: /dev/ttyUSB0: No such file or directory
before cat
cat: /dev/ttyUSB0: No such file or directory
catch
state: 0
USB-Storage found: usb0
state: 2

我做错了什么?

1 个答案:

答案 0 :(得分:2)

为什么它不起作用

在您的示例中,cat成功,这就是打印“cat after”并且未输入“catch group”的原因。

  

我想,当cat命令失败的时候,“cat after”将被写入

这个假设是错误的,“只有cat因为你使用&&运算符而成功{@}}才会写”cat“。

  

和||之后的部分将被解雇。

请注意,没有“groupfail”这样的东西可以让你使用命令组({ [...] })在Bash中实际模拟try / catch行为。考虑这个示例,在您的组中有多行:

{
  cmd1
  cmd2
} || { # catch block

只要cmd2成功,即使cmd1失败,您的程序也不会进入catch块。

如何模拟try / catch

但是,您可以使用&&运算符来模拟try / catch行为:

cmd1 && cmd2 && cmd3 || { # catch block

这也可以写成

{ cmd1 && cmd2 && cmd3 ; } || { # catch block

你看,无论你这样做,语法都有点笨拙。

也许这个related stackoverflow question也可以帮到你。

其他错误处理机制

最后但并非最不重要的是,应该提到两种常见的Bash错误处理机制:

  • ERR信号注册信号处理程序会导致Bash在命令返回非零退出状态时调用函数:

    trap error_handler ERR
    
    function error_handler() {
      echo error
    }
    
  • 设置errexit shell选项会导致程序在命令返回非零退出状态时终止(信号处理程序仍然执行):

    set -e