为什么相同的命令在 GitLab CI 中失败?
Why same command fails in GitLab CI?
以下命令在终端上运行完美,但在 GitLab 中同样的命令失败 CI。
echo Hello >> foo.txt; cat foo.txt | grep "test"; [[ $? -eq 0 ]] && echo fail || echo success
return 是 success
但 GitLab 中的相同命令 CI
$ echo Hello >> foo.txt; cat foo.txt | grep "test"; [[ $? -eq 0 ]] && echo fail || echo success
Cleaning up file based variables
ERROR: Job failed: command terminated with exit code 1
简直是失败了。我不知道为什么。
echo $SHELL
return /bin/bash
都在。
问题来源
考虑到 CI 上下文中的“隐含”set -e
,您观察到的行为非常标准。
更准确地说,您的代码包含三个复合命令:
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
而 grep "test"
命令 return 是一个非零退出代码(即 1
)。结果,脚本立即退出,最后一行没有执行。
请注意,此功能在 CI 上下文中很典型,因为如果某个中间命令在复杂脚本中失败,我们通常希望失败,并避免 运行 下一个命令(考虑到错误可能是“题外话”)。
您也可以在本地复制,例如:
bash -e -c "
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
"
这主要等同于:
bash -c "
set -e
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
"
相关手册页
更多见解:
- 在
set -e
上,参见 man 1 set
- 在
bash -e
上,参见 man 1 bash
如何解决这个问题?
您应该采用另一种措辞,避免 [[ $? -eq 0 ]]
事后检验。因此,可能 return 非零退出代码而不意味着失败的命令应该受到一些 if
:
的“保护”
echo Hello >> foo.txt
if cat foo.txt | grep "test"; then
echo fail
false # if ever you want to "trigger a failure manually" at some point.
else
echo success
fi
此外,请注意 grep "test" foo.txt
比 cat foo.txt | grep "test"
更加地道——这正是 UUOC 的一个实例(无用的使用猫)。
I have no idea why.
Gitlab 一次执行一个命令,并检查每个命令的退出状态。当退出状态不为零时,作业失败。
foo.txt
中没有 test
字符串,因此命令 cat foo.txt | grep "test"
以非零退出状态退出。因此作业失败。
以下命令在终端上运行完美,但在 GitLab 中同样的命令失败 CI。
echo Hello >> foo.txt; cat foo.txt | grep "test"; [[ $? -eq 0 ]] && echo fail || echo success
return 是 success
但 GitLab 中的相同命令 CI
$ echo Hello >> foo.txt; cat foo.txt | grep "test"; [[ $? -eq 0 ]] && echo fail || echo success
Cleaning up file based variables
ERROR: Job failed: command terminated with exit code 1
简直是失败了。我不知道为什么。
echo $SHELL
return /bin/bash
都在。
问题来源
考虑到 CI 上下文中的“隐含”set -e
,您观察到的行为非常标准。
更准确地说,您的代码包含三个复合命令:
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
而 grep "test"
命令 return 是一个非零退出代码(即 1
)。结果,脚本立即退出,最后一行没有执行。
请注意,此功能在 CI 上下文中很典型,因为如果某个中间命令在复杂脚本中失败,我们通常希望失败,并避免 运行 下一个命令(考虑到错误可能是“题外话”)。
您也可以在本地复制,例如:
bash -e -c "
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
"
这主要等同于:
bash -c "
set -e
echo Hello >> foo.txt
cat foo.txt | grep "test"
[[ $? -eq 0 ]] && echo fail || echo success
"
相关手册页
更多见解:
- 在
set -e
上,参见man 1 set
- 在
bash -e
上,参见man 1 bash
如何解决这个问题?
您应该采用另一种措辞,避免 [[ $? -eq 0 ]]
事后检验。因此,可能 return 非零退出代码而不意味着失败的命令应该受到一些 if
:
echo Hello >> foo.txt
if cat foo.txt | grep "test"; then
echo fail
false # if ever you want to "trigger a failure manually" at some point.
else
echo success
fi
此外,请注意 grep "test" foo.txt
比 cat foo.txt | grep "test"
更加地道——这正是 UUOC 的一个实例(无用的使用猫)。
I have no idea why.
Gitlab 一次执行一个命令,并检查每个命令的退出状态。当退出状态不为零时,作业失败。
foo.txt
中没有 test
字符串,因此命令 cat foo.txt | grep "test"
以非零退出状态退出。因此作业失败。