Search code examples
bashshellscriptingexit-code

shell exit code with code-block and pipe


In a shell script I'm using a code-block with curly brackets to pipe all output to console and a log-file with tee.

#!/bin/bash

{
  echo "Foo bar"
  echo "foo bar on STDERR" >&2
  ERRL=66
  exit 99
} 2>&1 | tee log-file.log

(This is only a small demo script, the original is much more complex)

The problem is, that the line exit 99 has no effect, the script ends with exit code 0. (This is the exit code of the tee command, I think)

I tried to add the line exit $ERRL at the end of the script, but it shows, that the variable $ERRL is empty outside the curly brackets.

What can I do, to end the script with an error code when something went wrong within the code-block -- without loosing the output to the log-file?


Solution

  • The least-intrusive way to redirect the output of your entire script is to do so once, up-front, without any blocking constructs involved:

    exec > >(tee log-file.log) 2>&1 # redirect stdout and stderr to a pipe to tee
    
    echo "Foo bar"
    echo "foo bar on STDERR" >&2
    ERRL=66
    exit 99
    

    Alternate options include using the pipefail setting...

    set -o pipefail
    { ... } 2>&1 | tee log-file.log
    

    ...or explicitly pulling the exit status out after-the-fact:

    { ... } 2>&1 | tee log-file.log
    exit "${PIPESTATUS[0]}"
    

    ...or just using a redirection that isn't a pipeline:

    { ... } > >(tee log-file.log) 2>&1