Tee 重置退出状态始终为 0

Tee resets exit status is always 0

我有一个像这样的简短脚本:

#!/bin/bash
<some_process> | tee -a /tmp/some.log  &
wait $(pidof <some_process_name>)
echo $?

无论 some_process 的退出状态如何,结果始终为 0。

我知道这里可以使用PIPESTATUS,但是为什么tee break wait?

好吧,由于某些特殊原因,文档没有提到这一点。但是,代码确实:

int wait_for (pid) { /*...*/
/* If this child is part of a job, then we are really waiting for the
job to finish. Otherwise, we are waiting for the child to finish. [...] */

if (job == NO_JOB)
  job = find_job (pid, 0, NULL);

所以它实际上是在等待整个作业,正如我们所知,它通常会产生链中最后一个命令的退出状态。

更糟糕的是,$PIPESTATUS 只能与最后一个 foreground 命令一起使用。

但是,您可以在子 shell 作业中使用 $PIPESTATUS,如下所示:

(<some_process> | tee -a /tmp/some.log; exit ${PIPESTATUS[0]}) &
# somewhere down the line:
wait %%<some_process>

这里的技巧是 使用 $PIPESTATUS 但也 wait -n:

检查这个例子:

#!/bin/bash

# start background task
(sleep 5 | false | tee -a /tmp/some.log ; exit ${PIPESTATUS[1]}) &

# foreground code comes here
echo "foo"

# wait for background task to finish
wait -n
echo $?

您总是获得 0 退出状态的原因是返回的退出状态是 管道中最后一个命令 的退出状态,即 tee.通过使用管道,您可以消除 <some_command>.

退出状态的正常检测

来自 bash 手册页:

The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.

所以...以下可能是您想要的:

#!/usr/bin/env bash

set -o pipefail
<some_command> | tee -a /tmp/some.log  &
wait %1
echo $?