try/catch 的 Bash 模拟未按预期工作

Posted

技术标签:

【中文标题】try/catch 的 Bash 模拟未按预期工作【英文标题】:Bash emulation of try/catch not working as expected 【发布时间】:2015-06-02 11:11:57 【问题描述】:

以下 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”之后发生了中断,因此实际状态不会改变,并且会再输入一次。然后 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

我做错了什么?

【问题讨论】:

按照你目前的逻辑,如果after cat被回显,则说明cat退出成功。 但是当我评论 '&& echo "after cat"' 时,行为保持不变 只要cat 成功(它似乎正在这样做),删除echo 不会有太大变化(我希望它也会成功)。 好的。当 cat 命令在串行适配器连接时启动时,它已成功。当我在 cat 已经启动并运行时断开适配器时,它是否也成功了? 【参考方案1】:

为什么它不起作用

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

我想,当 cat 命令在执行过程中失败时,会写“after cat”

这个假设是错误的,只有在cat 成功时才会写入“cat 之后”,因为您使用了&& 运算符。

比||之后的部分将被执行。

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


  cmd1
  cmd2
 ||  # catch block

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

如何模拟 try/catch

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

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

这也可以写成

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

你看,不管你怎么做,语法有点笨拙。

也许这个related *** question 也可以帮助你。

其他错误处理机制

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

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

trap error_handler ERR

function error_handler() 
  echo error

设置errexit shell 选项会导致您的程序在命令返回非零退出状态时立即终止(信号处理程序仍在执行):

set -e

【讨论】:

好的。但是当我使用 ' cmd1 && cmd2 && cmd3 ; || #catch block',catch块也只有cmd1才会执行,只有cmd1失败。我说的对吗? @Rush:不,只要其中一个命令失败,就会进入 catch 块。其余命令将不会执行。如果所有命令都成功,则不会进入 catch 块。 是的,我明白了。但是 catch-block 不会立即执行。仅当 cat 命令已正确启动时才会发生这种情况。这意味着串行适配器已插入。如果我在未插入串行适配器的情况下运行 cat 命令,则立即执行 catch-block @Rush:我不确定我是否理解 :-) 如果您的 cat 成功,那么将输入 catch 块。如果您的cat 失败,立即输入。 好吧,也许我首先尝试解释一下我对成功和不成功执行的定义:命令的退出代码告诉我命令是否成功。 0 表示成功,1 表示不成功。该代码是命令的退出代码,在本例中为 cat 命令。当我们谈论退出代码时,我们也在谈论具有 endet 的命令,对吗?这意味着我无法获得退出代码,而 cat 命令仍在我的文件中从串行转换器写入内容。但是:当我断开串行转换器时,cat 命令应该给我一些退出代码!= 0

以上是关于try/catch 的 Bash 模拟未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

麦克风权限未按预期工作

表格滚动未按预期工作

使用尺寸等级的设计未按预期工作

颤动 - WebViewController 中的 HTML 文件未按预期在 iOS 模拟器中加载

sh 如何在bash中执行try / catch块

Angular ngOnit () 未按预期工作