Bash忽略特定命令的错误

Viv*_*oel 399 linux bash

我正在使用以下选项

set -o pipefail
set -e
Run Code Online (Sandbox Code Playgroud)

在bash脚本中停止执行错误.我有100个脚本执行,我不想检查脚本的返回代码.但对于特定的脚本,我想忽略错误.我怎样才能做到这一点 ?

Igo*_*bin 679

解决方案:

particular_script || true
Run Code Online (Sandbox Code Playgroud)

例:

$ 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
Run Code Online (Sandbox Code Playgroud)

three 将永远不会打印.

另外,我想补充说,当pipefail打开时,当管道中的一个命令具有非零退出代码时,shell认为整个管道具有非零退出代码就足够了(pipefail关闭它必须是最后一个) .

$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0
Run Code Online (Sandbox Code Playgroud)

  • +1.正如Bash参考手册[解释](http://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtin),当`-e`属性时"shell不会退出"设置为"如果失败的命令是紧跟在`while`或`until`关键字之后的命令列表的一部分,则在`if`语句中测试的一部分,是在`&&`或`|中执行的任何命令的一部分. |`列表除了最后的`&&`或`||`之后的命令,管道中的任何命令但是最后一个,或者如果命令的返回状态是用`!`反转的话. (13认同)
  • `(ldd $2/bin/* || true) | grep“未找到”| 厕所-l || 真实` (4认同)
  • 如果要保留返回值(不退出)的选项,请尝试使用mycommand && true。这使您可以在后续步骤中检查返回代码并以编程方式进行处理。 (3认同)

Lar*_*off 164

只需|| true在要忽略错误的命令后添加.

  • 我认为添加这个很重要:这个方法将允许响应代码和错误消息持续存在,而"!" 下面概述的方法将更改响应代码,因此不会生成错误.当使用`set -e`并尝试捕获错误消息时,这很重要:例如`set -e; TEST = $(foo 2>&1 || true); echo $ TEST` (9认同)

Lil*_*ley 61

更简洁:

! particular_script
Run Code Online (Sandbox Code Playgroud)

POSIX规范有关set -e(重点煤矿):

启用此选项时,如果简单命令因Shell错误的后果中列出的任何原因而失败,或者返回退出状态值> 0,并且在while,until或if关键字后面不是复合列表的一部分,并且不是AND或OR列表的一部分,并且不是以!开头的管道!保留字,然后外壳应立即退出.

  • 这只是反转命令的退出代码,因此成功完成的命令将返回1而不是0并且使用`-e`失败脚本. (13认同)
  • 我的理解是`!`将阻止shell无论如何退出.[此脚本](http://pastebin.com/B6aRXGeA)在运行时显示消息"Still alive!",表示脚本已完成运行.你看到不同的行为吗? (12认同)
  • 你是对的,它会反转退出状态,但是当命令以0或1结束时不会崩溃脚本.我是不专心的.无论如何,感谢您引用文档,我将表达式添加到`if`子句并解决了问题. (6认同)

小智 61

如果您希望脚本在特定命令失败时不停止并且您还想保存失败命令的错误代码,以防万一!

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE
Run Code Online (Sandbox Code Playgroud)

  • 我想这可能是最好的答案。无论如何,这就是我一直在寻找的东西。我不希望 shell 退出,但我确实想知道错误,以便我可以做出响应。多谢! (8认同)
  • @Ankita13因为如果它为零,则第一个“命令”成功,并且需要运行“||”之后的内容。读作:如果“命令”失败,则执行“EXIT_CODE=$?”。你可能可以只执行```命令|| echo "$?"``` 或使用“trap”进行更详细的调试。请参阅此-> /sf/answers/427731251/ (2认同)

Tim*_*imo 38

您也可以使用"noop"或null实用程序(如POSIX规范中所述):而不是"不执行任何操作",而不是"返回true ".你会节省几封信.:)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."
Run Code Online (Sandbox Code Playgroud)

  • 虽然||:不像||那样清楚 是的(这可能会混淆非专家用户),我喜欢它的简洁 (2认同)

Kon*_*ard 24

我找到了另一种方法来解决这个问题:

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
Run Code Online (Sandbox Code Playgroud)

您可以关闭错误失败功能,set +e现在将忽略该行之后的所有错误。完成后,如果您希望脚本因任何错误而再次失败,则可以使用set -e.

应用后,当找不到文件时,整个脚本不会再失败set +efind同时,find仍然打印错误消息,但整个脚本继续执行。因此,如果这导致了问题,则很容易调试。

这对于 CI 和 CD 很有用(例如在 GitHub Actions 中)。


小智 17

感谢上面提供的简单解决方案:

<particular_script/command> || true
Run Code Online (Sandbox Code Playgroud)

以下构造可用于脚本步骤的其他操作/故障排除和其他流程控制选项:

if <particular_script/command>
then
   echo "<particular_script/command> is fine!"
else
   echo "<particular_script/command> failed!"
   #exit 1
fi
Run Code Online (Sandbox Code Playgroud)

如果需要的话,我们可以停止进一步的行动exit 1


vol*_*gas 8

如果您想防止脚本失败收集返回码:

command () {
    return 1  # or 0 for success
}

set -e

command && returncode=$? || returncode=$?
echo $returncode
Run Code Online (Sandbox Code Playgroud)

returncode 无论命令成功还是失败,都会被收集。


小智 6

output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status
Run Code Online (Sandbox Code Playgroud)

使用它创建日志文件的示例

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
Run Code Online (Sandbox Code Playgroud)