3

I have a short script like this:

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

The result is always 0, irrespective of the exit status of some_process.

I know PIPESTATUS can be used here, but why does tee break wait?

Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38
Jeryl Vaz
  • 68
  • 4

3 Answers3

3

Well, this is something that, for some peculiar reason, the docs don't mention. The code, however, does:

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);

So it's actually waiting for the whole job, which, as we know, normally yields the exit status of the last command in the chain.

To make matters worse, $PIPESTATUS can only be used with the last foreground command.

You can, however, utilize $PIPESTATUS in a subshell job, like this:

(<some_process> | tee -a /tmp/some.log; exit ${PIPESTATUS[0]}) &
# somewhere down the line:
wait %%<some_process>
Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38
1

The trick here is to use $PIPESTATUS but also wait -n:

Check this example:

#!/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 $?
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
0

The reason you always get an exit status of 0 is that the exit status returned is that of the last command in the pipeline, which is tee. By using a pipe, you eliminate the normal detection of exit status of <some_command>.

From the bash man page:

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.

So... The following might be what you want:

#!/usr/bin/env bash

set -o pipefail
<some_command> | tee -a /tmp/some.log  &
wait %1
echo $?
ghoti
  • 45,319
  • 8
  • 65
  • 104