解决方案:
particular_script || true
例子:
$ cat /tmp/1.sh
particular_script()
{
false
}
set -e
echo one
particular_script || true
echo two
particular_script
echo three
$ bash /tmp/1.sh
one
two
three
永远不会被打印。
另外,我想补充一点,当 pipefail
打开时,当管道中的命令之一具有非零退出代码(关闭 pipefail
)时,shell 认为整个管道具有非零退出代码就足够了它必须是最后一个)。
$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0
只需在要忽略错误的命令后添加 || true
。
set -e
并尝试捕获错误消息时很重要:例如set -e; TEST=$(foo 2>&1 || true); echo $TEST
set -e
,将未找到的 bash 命令从 stderr 重定向到 $TEST
。这如何保留响应代码?
set -e; TEST=$(foo 2>&1) || printf "ERROR $?: $TEST\n"
不要停止并保存退出状态
以防万一您希望脚本在特定命令失败时不停止,并且您还想保存失败命令的错误代码:
set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE
command
为零,则需要运行 ||
之后的内容。将其读作:如果 command
失败,则执行 EXIT_CODE=$?
。您可能只需执行 command || echo "$?"
或使用“陷阱”进行更详细的调试。看到这个-> stackoverflow.com/a/6110446/10737630
更简洁:
! particular_script
从关于 set -e
的 POSIX specification(强调我的):
当此选项打开时,如果简单命令由于 Shell 错误的后果中列出的任何原因而失败或返回退出状态值 >0,并且在一段时间、直到或 if 关键字之后不属于复合列表的一部分,并且不是 AND 或 OR 列表的一部分,也不是前面有 ! 的管道保留字,则shell应立即退出。
-e
使脚本失败。
if
子句中并解决了问题。
particular_script
的返回值,但如果 particular script
是一个函数,我确实不想忽略语句的返回值函数里面。 ||
解决方案将忽略 particular_script
函数体内的所有返回码,这通常不是您想要的 (stackoverflow.com/a/37191242/985292)。
||
在破折号中不起作用,但确实如此。谢谢!
除了“返回 true”,您还可以使用“noop”或 null 实用程序(如 POSIX specs 中所述):
并且只是“什么都不做”。你会省下几封信。 :)
#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."
alias null=:
,如果您觉得更清楚,可以使用 null
代替 :
。
如果您想防止脚本失败并收集返回码:
command () {
return 1 # or 0 for success
}
set -e
command && returncode=$? || returncode=$?
echo $returncode
无论命令成功还是失败,都会收集 returncode
。
感谢上面的简单解决方案:
<particular_script/command> || true
以下构造可用于脚本步骤的附加操作/故障排除和附加流控制选项:
if <particular_script/command>
then
echo "<particular_script/command> is fine!"
else
echo "<particular_script/command> failed!"
#exit 1
fi
如果需要,我们可以停止进一步的操作和exit 1
。
从这里没有解决方案对我有用,所以我找到了另一个解决方案:
set +e
find "./csharp/Platform.$REPOSITORY_NAME/obj" -type f -iname "*.cs" -delete
find "./csharp/Platform.$REPOSITORY_NAME.Tests/obj" -type f -iname "*.cs" -delete
set -e
您可以通过 set +e
关闭错误失败,这将忽略该行之后的所有错误。完成后,如果您希望脚本在出现任何错误时再次失败,您可以使用 set -e
。
应用 set +e
后,当找不到文件时,find
不再使整个脚本失败。同时,仍然会打印来自 find
的错误消息,但整个脚本会继续执行。因此,如果这导致问题很容易调试。
这对 CI 和 CD 很有用。
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status
使用它创建日志文件的示例
log_event(){
timestamp=$(date '+%D %T') #mm/dd/yy HH:MM:SS
echo -e "($timestamp) $event" >> "$log_file"
}
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
if [ "$exit_status" = 0 ]
then
event="$output"
log_event
else
event="ERROR $output"
log_event
fi
在使用 CLI 工具时,我一直在使用下面的代码片段,我想知道是否存在某些资源,但我不关心输出。
if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
echo "none exist actually exist!"
fi
if [ -r not_exist ]
我有点喜欢这个解决方案:
: `particular_script`
执行反引号之间的命令/脚本,并将其输出馈送到命令“:”(相当于“真”)
$ false
$ echo $?
1
$ : `false`
$ echo $?
0
编辑:修正了丑陋的错字
虽然 || true
是首选,但您也可以这样做
var=$(echo $(exit 1)) # it shouldn't fail
不定期副业成功案例分享
-e
属性时,shell 不会退出”“如果失败的命令是紧跟while
或until
关键字的命令列表的一部分,则if
语句中的测试,在&&
或||
列表中执行的任何命令的一部分,除了最后一个&&
或||
之后的命令,管道中除最后一个之外的任何命令,或者如果命令的返回状态正在与!
反转。"(ldd $2/bin/* || true) | grep "not found" | wc -l
脚本在 ldd 返回失败时在此行之后终止(ldd $2/bin/* || true) | grep "not found" | wc -l || true
set -o pipefail
。当grep
什么也没找到时,它返回非零退出代码,并且 shell 认为整个管道具有非零退出代码就足够了。