我有一个简短的脚本,像这样:
#!/bin/bash
<some_process> | tee -a /tmp/some.log &
wait $(pidof <some_process_name>)
echo $?
无论 some_process 的退出状态如何,结果始终为0。
我知道可以使用 PIPESTATUS,在这里,但为什么 tee 会打断 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
只能与最后一个 前台 命令一起使用。
但是,您可以在子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 $?
-n
,你可以直接给出一个特定的作业编号。 - Yam Marcovic-n
,wait
始终会返回 0
。我承认 help wait
没有提到这一点。让我调查一下。 - hek2mgl你总是得到一个退出状态为0
的原因是,返回的退出状态是“管道中最后一个命令”的退出状态,也就是tee
。通过使用管道,你消除了对<some_command>
正常检测退出状态的影响。
从bash手册中可以看到:
如果启用了pipefail选项,管道的返回状态是最后一个(最右边的)以非零状态退出的命令的值,或者如果所有命令都成功退出,则为零。
所以... 以下可能是你想要的:
#!/usr/bin/env bash
set -o pipefail
<some_command> | tee -a /tmp/some.log &
wait %1
echo $?
wait
命令。所以如果它成功完成,退出状态将为0。 - Avihoo Mamkawait
应该返回指定 pid 的退出状态。 - Yam Marcovic