gpt4 book ai didi

bash - 为什么将 `trap -` 放入函数中时不起作用?

转载 作者:行者123 更新时间:2023-12-04 10:37:03 25 4
gpt4 key购买 nike

精简版

在 Bash 脚本中,我激活了一个陷阱,然后通过调用 trap - EXIT ERR SIGHUP SIGINT SIGTERM 停用它。 .当我直接在脚本中进行停用时,它可以工作。但是,当我将完全相同的代码行放在 Bash 函数中时,它会被忽略,即,如果稍后命令返回不同于零的退出代码,则陷阱仍会被激活。为什么?

长版

我有一堆函数可以处理陷阱:

trap_stop()
{
echo "trap_stop"
trap - EXIT ERR SIGHUP SIGINT SIGTERM
}

trap_terminate()
{
local exitCode="$?"
echo "trap_terminate"
trap_stop

local file="${BASH_SOURCE[1]}"
local stack=$(caller)
local line="${stack% *}"

if [ $exitCode == 0 ]; then
echo "Finished."
else
echo "The initialization failed with code $exitCode in $file:${line}."
fi

exit $exitCode
}

trap_start()
{
echo "trap_start"
trap "trap_terminate $LINENO" EXIT ERR SIGHUP SIGINT SIGTERM
}

像这样使用时:
trap_start  # <- Trap started.

echo "Stopping traps."
trap_stop # <- Trap stopped before calling a command which exits with exit code 2.

echo "Performing a command which will fail."
ls /tmp/missing
exit_code="$?"

echo "The result of the check is $exit_code."

我得到以下输出:
trap_startStopping traps.trap_stopPerforming a command which will fail.ls: cannot access '/tmp/missing': No such file or directorytrap_terminatetrap_stopThe initialization failed with code 2 in ./init:41.

Despite the fact that function deactivating the trap was called, the trap was still triggered when calling ls on a directory which doesn't exist.

On the other hand, when I replace the call to trap_stop by the actual trap - statement, like this:

trap_start

echo "Stopping traps."
trap - EXIT ERR SIGHUP SIGINT SIGTERM # <- This statement replaced the call to `trap_stop`.

echo "Performing a command which will fail."
ls /tmp/missing
exit_code="$?"

echo "The result of the check is $exit_code."

那么输出是正确的,即陷阱没有被激活,我到达了脚本的末尾。

陷阱_开始
停止陷阱。
执行将失败的命令。
ls: 无法访问 '/tmp/missing': 没有那个文件或目录
检查结果为 2。

为什么要搬家 trap -到一个函数使它停止工作?

最佳答案

编辑 (@KamilCuk 提供):如果您的 bash 版本低于 4.4,请升级您的 bash,它可以解决问题。

我在你的代码中添加了一些调试:

echo "Stopping traps."
trap -p
trap_stop # <- Trap stopped before calling a command which exits with exit code 2.
trap -p

并得到:
Stopping traps.
trap -- 'trap_terminate 29' EXIT
trap -- 'trap_terminate 29' SIGHUP
trap -- 'trap_terminate 29' SIGINT
trap -- '' SIGFPE
trap -- 'trap_terminate 29' SIGTERM
trap -- '' SIGXFSZ
trap -- '' SIGPWR
trap -- 'trap_terminate 29' ERR
trap_stop
trap -- '' SIGFPE
trap -- '' SIGXFSZ
trap -- '' SIGPWR
trap -- 'trap_terminate 29' ERR

如您所见, trap -部分确实有效,除了 ERR健康)状况。

经过一些手册页时间:
echo "Stopping traps."
set -E
trap_stop # <- Trap stopped before calling a command which exits with exit code 2.

产量:
trap_start
Stopping traps.
trap_stop
Performing a command which will fail.
ls: cannot access '/tmp/missing': No such file or directory
The result of the check is 2.

bash(1) 的相关部分:

-E If set, any trap on ERR is inherited by shell functions, command substitutions, and commands executed in a subshell environment. The ERR trap is normally not inherited in such cases.



也就是说,这似乎是 bash 中的一个错误:
#!/bin/bash

t1()
{
trap 'echo t1' ERR
}

t2()
{
trap 'echo t2' ERR
}

t1
false
t2
false

产量:
t1
t1

而我至少期望:
t1
t2

关于bash - 为什么将 `trap -` 放入函数中时不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60127929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com