除非在函数或子 shell 中使用,否则命令退出时的陷阱不起作用

Ini*_*ian 3 shell bash signals trap error-handling

我正在trap使用示例代码对无效的命令返回码进行一些试验

#!/bin/bash

# Exit on error
trap 'echo 'exiting..';exit' ERR
set -e

h=1
b=$((h+)) # <----- command causing the error
echo $?
echo $b
echo "end"
Run Code Online (Sandbox Code Playgroud)

即使有违规指令,我也无法导致陷阱发生。但是如果我在子shell中运行相同

function junk() {
h=1
b=$((h+))
echo "Exit code:$?"
echo $b
echo "end"
echo "Hello"
}

junk
Run Code Online (Sandbox Code Playgroud)

(或)在子shell中运行整个指令作为

(h=1
b=$((h+))
echo "Exit code:$?"
echo $b
echo "end"
echo "Hello"
)
Run Code Online (Sandbox Code Playgroud)

能够捕获命令失败并EXIT捕获陷阱并相应地打印消息。

我知道使用 set -e

-e  errexit When set, the shell exits when a simple command in a command list exits
    non-zero (FALSE). This is not done in situations, where the exit code is already checked 
    (if, while, until, ||, &&)
Run Code Online (Sandbox Code Playgroud)

但我找不到正确的参考,它说只发生在子外壳或函数或类似的东西上。

如果我在这里遗漏了一些基本的东西,请告诉我。

xhi*_*nne 6

您缺少的是set -esigspec 和 sigspecERR都适用于命令执行(以非零值退出的命令)。你在这里遇到的b=$((h+))是一个解析错误。该命令没有被执行,因为它不被理解。

为什么它在函数或子 shell 中工作?因为这个解析错误使得包含脚本(无论是函数还是子 shell)作为一个整体失败。换句话说,这不是b=$((h+))触发你的陷阱(你的子 shell 中没有设置陷阱),这是对junk或 子shell的调用失败。

  • @Inian 哦,我明白了。我以为您想要引用失败的命令。无论如何,这是“bash”手册中描述此行为的部分:« _如果 sigspec 是 ERR,则每当管道(可能由单个简单命令组成)、列表或复合命令时,都会执行命令 arg返回非零退出状态 [...]_ » (2认同)