首页 > 解决方案 > Bash:获取打印函数的状态

问题描述

从另一个函数调用 bash 函数,该函数需要打印其输出并获取其返回的状态码:

cmd="/usr/bin/foo_cmd"

# Print message both to stdout and FD5 (I need this because I have to print the message during the script execution and have it sent via e-mail)
msg() {
    msg="$1"
    echo "$msg" | tee /dev/fd/5
}

# Command execution
cmd_exec() {
    cmd="$1"
    exec 5>&2
    output=$($cmd 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
    status=$?
    echo "Exit status code: $status"
    echo "$output"
    return $status
}

main() {
    exec 5>&2
    echo $(cmd_exec "$cmd")
    status=$?
    msg "Function exit status code: ${status}"
    if [ "$status" -ne "0" ]; then
        ... do something ...
    fi

    return $status
}

mail_text="$(main)"
status=$?

# Check exit status code and compose the mail message
if [ "$status" -ne "0" ]; then
    ... do something ...
fi

... do something else ...

main 函数总是得到状态码 0,因为它不是 的状态码,$cmd而是的状态码echo

如何解决此问题以获取 的真实状态代码$cmd

标签: bash

解决方案


第一点:

 echo $(cmd_exec "$cmd")

总是会成功echo返回,就像成功返回一样。

您应该首先将命令替换保存在变量中,然后调用 echo:

 var="$(cmd_exec "$cmd")"
 status="$?"
 echo "$var"

命令替换返回最后一个执行命令的$( ... )退出状态,如果只有一个,则变量替换保留退出状态$( ... )

第二点:

来自bash 手册

管道的退出状态是管道中最后一个命令的退出状态,除非启用了 pipefail 选项(请参阅 The Set Builtin)。如果启用了 pipefail,则管道的返回状态是最后一个(最右边)以非零状态退出的命令的值,如果所有命令都成功退出,则返回零。

您可以使用set -o pipefail而不是检查和echo ${PIPESTATUS[0]}的返回状态。tee$cmd


推荐阅读