我有一个像这样的简短剧本:
#!/bin/bash
<some_process> | tee -a /tmp/some.log &
wait $(pidof <some_process_name>)
echo $?
无论some_process的退出状态如何,结果始终为0。
我知道PIPESTATUS可以在这里使用,但为什么打破 wait
?
答案 0 :(得分:3)
嗯,出于一些特殊的原因,这些文件并没有提及。但是,代码确实:
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>
答案 1 :(得分:0)
这里的诀窍是使用 $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 $?
答案 2 :(得分:0)
您始终获得退出状态0
的原因是退出的退出状态是管道中最后一个命令的退出状态,即tee
。通过使用管道,您可以消除<some_command>
退出状态的正常检测。
来自bash手册页:
管道的返回状态是最后一个命令的退出状态,除非启用了pipefail选项。如果启用了pipefail,则管道的返回状态是以非零状态退出的最后(最右侧)命令的值,如果所有命令都成功退出,则返回零。
所以...以下可能是你想要的:
#!/usr/bin/env bash
set -o pipefail
<some_command> | tee -a /tmp/some.log &
wait %1
echo $?