gpt4 book ai didi

linux - Bash 和 Dash 不一致地使用 `errexit` 检查命令替换错误代码

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:35:29 24 4
gpt4 key购买 nike

我似乎在 dashbash 使用 errexit 选项检查错误条件的方式上遇到了非常非常奇怪的不一致.

同时使用 dashbash 没有 set -e/set -o errexit 选项,以下程序:

foo()
{
echo pre
bar=$(fail)
echo post
}

foo

将打印以下内容(dash 的错误字符串略有不同):

pre
./foo.sh: line 4: fail: command not found
post

使用 errexit 选项,它将打印以下内容:

pre
./foo.sh: line 4: fail: command not found

然而,令人惊讶的是,如果 barlocal,程序将始终 echo pre发布。更具体地说,同时使用 dashbash 不带 errexit 选项,以下程序:

foo()
{
echo pre
local bar=$(fail)
echo post
}

foo

将打印以下内容:

pre
./foo.sh: line 4: fail: command not found
post

换句话说,errexit 似乎没有检查分配给局部变量的命令替换的返回值,但如果变量是全局变量,则会检查。

如果这两个 shell 都没有发生,我会倾向于认为这只是一个角落案例错误。由于 dash 是专门为符合 POSIX 标准而设计的,我想知道这种行为是否实际上是由 POSIX 标准指定的,尽管我很难想象这有什么意义。

dash(1) 关于 errexit 有这样的说法:

If not interactive, exit immediately if any untested command fails. The exit status of a command is considered to be explicitly tested if the command is used to control an if, elif, while, or until; or if the command is the left hand operand of an “&&” or “||” operator.

bash(1) 有点冗长,但我很难理解它:

Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command (see SHELL GRAMMAR above), exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits. This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell.

If a compound command or shell function executes in a context where -e is being ignored, none of the commands executed within the compound command or function body will be affected by the -e setting, even if -e is set and a command returns a failure status. If a compound command or shell function sets -e while executing in a context where -e is ignored, that setting will not have any effect until the compound command or the command containing the function call completes.

最佳答案

TL;DR local 的退出状态“隐藏”了出现在其参数之一中的任何命令替换的退出状态。


变量赋值的退出状态记录很少(或者至少,我在快速浏览各种手册页和 POSIX 规范时找不到任何细节)。据我所知,退出状态被视为发生在赋值值中的 last 命令替换的退出状态,如果没有命令替换,则为 0。非最终命令替换似乎包含在“已测试”情况的列表中,就像这样的分配

foo=$(false)$(true)

不退出并设置了 errexit

然而,

local 是一个命令本身,其退出状态通常为 0,独立于其参数中出现的任何命令替换。也就是说,虽然

foo=$(false)

退出状态为1,

local foo=$(false)

退出状态为 0,参数中的任何命令替换看起来都被视为“已测试”用于 errexit

关于linux - Bash 和 Dash 不一致地使用 `errexit` 检查命令替换错误代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33844028/

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