子shell

问题描述

我有一个经常失败的脚本。传递正确的退出代码至关重要。

代码可以正常工作:

#!/usr/bin/env bash

function my_function {
    echo "Important output"
    exit 1
}

function cleanup {
  MY_EXIT_CODE=$?
  echo "MY_EXIT_CODE: ${MY_EXIT_CODE}"
}

trap cleanup EXIT

my_function

MY_EXIT_CODE的期望值为1,并且在脚本也给我echo $?之后(如预期的那样)运行1

但是,我需要获得my_function的完整输出到变量和控制台输出。为此,按照此answer(似乎本身基于此answer)的建议,我将代码更改为

#!/usr/bin/env bash

function my_function {
    echo "Important output"
    exit 1
}

function cleanup {
  MY_EXIT_CODE=$?
  echo "MY_EXIT_CODE: ${MY_EXIT_CODE}"
}

trap cleanup EXIT

exec 5>&1
FF=$(my_function|tee /dev/fd/5)

现在退出代码错误的。是0,而应该是1。我知道这在某种程度上与subshel​​l处理有关,但是我不知道如何解决

解决方法

现在退出代码是错误的。是0,应该是1

不,您的假设是错误的。假设tee成功,则退出代码应为0。从posix shell manual

如果保留字!不在管道之前,退出状态应为管道中最后指定的命令的退出状态。

管道中的“最后一条命令”是最右边的命令。因为您的情况tee以0退出,所以FF=$(.... | tee)的退出状态为零。

解决方法。

这取决于您要实现的行为。通常,在bash中,您可能set -o pipefail总是会捕获错误。

,

似乎只是简单地说明

set -o pipefail

在脚本文件的开头完成了操作。

,

是的,它是子外壳和管道,请尝试这样

FF=$(my_function|tee /dev/fd/5; exit $PIPESTATUS)