我有一个script.sh
,我必须正确诊断其中的任何错误,因此prova
如果出现错误,该函数不应中途停止,而应继续到最后报告其错误消息。为此,我必须使用 OR 运算符从子 shell 中捕获任何错误代码||
,但这样做会导致子 shell 在第一个失败的命令时不会退出,而这不是我想要的。
例子:
假设我在包含脚本的目录中,从 shell 运行以下命令:
./script.sh
如果我不使用 OR||
运算符,函数就不会继续执行到最后,因此不会产生错误消息:
#!/bin/bash -e
...
prova () {
local function_name="${FUNCNAME[0]}"
local exit_code=0
(
set -e
prova1
prova2
prova3
)
echo "$function_name: An error has occurred." >&2
return $exit_code
}
prova
...
标准错误:
./script.sh: line 7: prova1: command not found
如果我使用 OR||
运算符,它会执行所有 3 个命令,但它仍应在第一个捕获其退出代码的命令处停止:
#!/bin/bash -e
...
prova () {
local function_name="${FUNCNAME[0]}"
local exit_code=0
(
set -e
prova1
prova2
prova3
) || exit_code=$?
if [[ $exit_code -ne 0 ]]; then
echo "$function_name: An error has occurred." >&2
fi
return $exit_code
}
prova
...
标准错误:
./script.sh: line 7: prova1: command not found
./script.sh: line 8: prova2: command not found
./script.sh: line 9: prova3: command not found
prova: An error has occurred.
我想要这个 StdErr:
./script.sh: line 7: prova1: command not found
prova: An error has occurred.
我如何获得它?
答案1
因为复合命令是 || 列表的一部分,而不是该列表中的最后一个,-e
所以选项在该复合命令中不起作用。请参阅set
内置命令的文档bash 手册:
-e 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.
要在第一个命令失败后退出子 shell,可以使用如下代码:
prova () {
local exit_code=0
(
prova1 &&
prova2 &&
prova3
) || exit_code=$?
return $exit_code
}
您甚至可能不需要在函数中使用子shell。
如果您需要-e
在函数中使用复合命令,那么可以使用如下命令:
#!/bin/bash
prova() {
(
set -e
prova1
prova2
prova3
)
local exit_code=$?
if [[ $exit_code -ne 0 ]]; then
echo "${FUNCNAME[0]}: An error has occurred." >&2
fi
return $exit_code
}
prova