Bash - 如果语句之一 return 错误代码 != 0,则中断条件子句
Bash - break conditional clause if one of the statements return error code != 0
我有以下 bash 脚本,它 运行 在我的 CI 上并且打算 运行 我的代码在物理 MacOS 和几个 docker Linux 图片:
if [[ "$OS_NAME" == "mac_os" ]]; then
make all;
run_test1;
run_test2;
make install;
else
docker exec -i my_docker_image bash -c "make all";
docker exec -i my_docker_image bash -c "run_test1";
docker exec -i my_docker_image bash -c "run_test2";
docker exec -i my_docker_image bash -c "make install";
fi
如果测试失败(run_test1
或 run_test2
)他们 return 错误代码 1。如果他们通过他们 return 错误代码 0。
整个脚本 运行 具有 set -e
,所以只要它看到 0 以外的退出代码,它就会停止并导致整个构建失败。
当前的问题是,当 run_test1
和 run_test2
位于条件子句内时 - 当它们失败并且 return 错误代码 1 时,条件子句不会中断并且尽管测试未通过,但构建成功。
所以我有两个问题:
- 如果命令之一 return 错误代码不是 0,如何中断条件从句?
- 如何以整个子句都会 return 错误代码(因此整个构建将失败)的方式打破条件子句?
您的代码应该按预期工作,让我们演示一下:
#!/usr/bin/env bash
set -e
var="test"
if [[ $var = test ]]; then
echo "Hello"
cat non_existing_file &> /dev/null
echo "World"
else
echo "Else hello"
cat non_existing file &> /dev/null
fi
echo I am done
这将按预期仅输出 "Hello"。如果它对您的工作方式不同,则意味着您没有提供足够的代码。让我们尝试更改上面的代码并在 set -e
被忽略时显示一些示例,就像您的情况一样:
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.
现在让我们引用相同的手册,看看忽略-e的一些情况:
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 in an if statement, 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 status is being
inverted with !.
从这里我们可以看出,例如,如果您在一个函数中有上面的代码并使用 if
测试该函数,set -e
将被忽略:
#!/usr/bin/env bash
set -e
f() {
var="test"
if [[ $var = test ]]; then
echo "Hello"
cat non_existing_file &> /dev/null
echo "World"
else
echo "Else hello"
cat non_existing file &> /dev/null
fi
}
if f; then echo "Function OK!"; fi
echo I am done
函数 f
在忽略 set -e
的上下文中执行(if 语句),这意味着 set -e
不会影响在此函数中执行的任何命令。此代码输出:
Hello
World
Function OK!
I am done
当您在 && 或 || 中执行函数时,同样的规则适用列表。如果将行 if f; then echo "Function OK!"; fi
更改为 f && echo "Function OK"
,您将获得相同的输出。我相信后者可能是你的情况。
即便如此,您的 第二个问题 可以通过添加 || exit
:
轻松解决
run_test1 || exit 1;
run_test2 || exit 1;
你的第一个问题是微不足道的,例如,如果你在一个函数中。然后你可以简单地return
。或者在一个循环里面,那么你可以break
。如果你不是,打破条件条款就没那么容易了。看看这个.
set -e
可能是一件令人惊讶的事情,因为它在许多情况下都被忽略了。请谨慎使用并注意这些情况。
我有以下 bash 脚本,它 运行 在我的 CI 上并且打算 运行 我的代码在物理 MacOS 和几个 docker Linux 图片:
if [[ "$OS_NAME" == "mac_os" ]]; then
make all;
run_test1;
run_test2;
make install;
else
docker exec -i my_docker_image bash -c "make all";
docker exec -i my_docker_image bash -c "run_test1";
docker exec -i my_docker_image bash -c "run_test2";
docker exec -i my_docker_image bash -c "make install";
fi
如果测试失败(run_test1
或 run_test2
)他们 return 错误代码 1。如果他们通过他们 return 错误代码 0。
整个脚本 运行 具有 set -e
,所以只要它看到 0 以外的退出代码,它就会停止并导致整个构建失败。
当前的问题是,当 run_test1
和 run_test2
位于条件子句内时 - 当它们失败并且 return 错误代码 1 时,条件子句不会中断并且尽管测试未通过,但构建成功。
所以我有两个问题:
- 如果命令之一 return 错误代码不是 0,如何中断条件从句?
- 如何以整个子句都会 return 错误代码(因此整个构建将失败)的方式打破条件子句?
您的代码应该按预期工作,让我们演示一下:
#!/usr/bin/env bash
set -e
var="test"
if [[ $var = test ]]; then
echo "Hello"
cat non_existing_file &> /dev/null
echo "World"
else
echo "Else hello"
cat non_existing file &> /dev/null
fi
echo I am done
这将按预期仅输出 "Hello"。如果它对您的工作方式不同,则意味着您没有提供足够的代码。让我们尝试更改上面的代码并在 set -e
被忽略时显示一些示例,就像您的情况一样:
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.
现在让我们引用相同的手册,看看忽略-e的一些情况:
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 in an if statement, 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 status is being inverted with !.
从这里我们可以看出,例如,如果您在一个函数中有上面的代码并使用 if
测试该函数,set -e
将被忽略:
#!/usr/bin/env bash
set -e
f() {
var="test"
if [[ $var = test ]]; then
echo "Hello"
cat non_existing_file &> /dev/null
echo "World"
else
echo "Else hello"
cat non_existing file &> /dev/null
fi
}
if f; then echo "Function OK!"; fi
echo I am done
函数 f
在忽略 set -e
的上下文中执行(if 语句),这意味着 set -e
不会影响在此函数中执行的任何命令。此代码输出:
Hello
World
Function OK!
I am done
当您在 && 或 || 中执行函数时,同样的规则适用列表。如果将行 if f; then echo "Function OK!"; fi
更改为 f && echo "Function OK"
,您将获得相同的输出。我相信后者可能是你的情况。
即便如此,您的 第二个问题 可以通过添加 || exit
:
run_test1 || exit 1;
run_test2 || exit 1;
你的第一个问题是微不足道的,例如,如果你在一个函数中。然后你可以简单地return
。或者在一个循环里面,那么你可以break
。如果你不是,打破条件条款就没那么容易了。看看这个
set -e
可能是一件令人惊讶的事情,因为它在许多情况下都被忽略了。请谨慎使用并注意这些情况。