bash 当'set -e'处于活动状态时,Bash获取命令的退出状态?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18621990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 06:27:55  来源:igfitidea点击:

Bash get exit status of command when 'set -e' is active?

bash

提问by David Wolever

I generally have -eset in my Bash scripts, but occasionally I would like to run a command and get the return value.

我通常-e在我的 Bash 脚本中设置,但偶尔我想运行一个命令并获取返回值。

Without doing the set +e; some-command; res=$?; set -edance, how can I do that?

不做set +e; some-command; res=$?; set -e舞蹈,我怎么能做到呢?

回答by Adrian Frühwirth

From the bashmanual:

bash手册:

The shell does not exit if the command that fails is [...] part of any command executed in a && or || list [...].

如果失败的命令是在 && 或 || 中执行的任何命令的 [...] 一部分,则 shell 不会退出 列表 [...]。

So, just do:

所以,只要这样做:

#!/bin/bash

set -eu

foo() {
  # exit code will be 0, 1, or 2
  return $(( RANDOM % 3 ))
}

ret=0
foo || ret=$?
echo "foo() exited with: $ret"

Example runs:

示例运行:

$ ./foo.sh
foo() exited with: 1
$ ./foo.sh
foo() exited with: 0
$ ./foo.sh
foo() exited with: 2

This is the canonical way of doing it.

这是规范的做法。

回答by KitsuneYMG

as an alternative

作为备选

ans=0
some-command || ans=$?

回答by Phil Miller

Maybe try running the commands in question in a subshell, like this?

也许尝试在子shell中运行有问题的命令,像这样?

res=$(some-command > /dev/null; echo $?)

回答by konsolebox

Use a wrapper function to execute your commands:

使用包装函数来执行您的命令:

function __e {
    set +e
    "$@"
    __r=$?
    set -e
}

__e yourcommand arg1 arg2

And use $__rinstead of $?:

并使用$__r代替$?

if [[ __r -eq 0 ]]; then
    echo "success"
else
    echo "failed"
fi

Another method to call commands in a pipe, only that you have to quote the pipe. This does a safe eval.

在管道中调用命令的另一种方法,只是您必须引用管道。这是一个安全的评估。

function __p {
    set +e
    local __A=() __I
    for (( __I = 1; __I <= $#; ++__I )); do
        if [[ "${!__I}" == '|' ]]; then
            __A+=('|')
        else
            __A+=("\"$$__I\"")
        fi
    done
    eval "${__A[@]}"
    __r=$?
    set -e
}

Example:

例子:

__p echo abc '|' grep abc

And I actually prefer this syntax:

我实际上更喜欢这种语法:

__p echo abc :: grep abc

Which I could do with

我可以用

...
        if [[ ${!__I} == '::' ]]; then
...