cis
cis

Reputation: 1377

Wrong exit code for variable function call assignment in subshell

I have a script which quite often fails. It is crucial that the correct exit code is passed on.

This code works as expected:

#!/usr/bin/env bash

function my_function {
    echo "Important output"
    exit 1
}

function cleanup {
  MY_EXIT_CODE=$?
  echo "MY_EXIT_CODE: ${MY_EXIT_CODE}"
}

trap cleanup EXIT

my_function

MY_EXIT_CODE is 1 as expected and running echo $? after the script gives me 1 as well (as expected)

However, I need to get the complete output of my_function both to a variable and the console output. In order to do so, as advised in this answer (which seems itself based on this answer) I changed my code into

#!/usr/bin/env bash

function my_function {
    echo "Important output"
    exit 1
}

function cleanup {
  MY_EXIT_CODE=$?
  echo "MY_EXIT_CODE: ${MY_EXIT_CODE}"
}

trap cleanup EXIT

exec 5>&1
FF=$(my_function|tee /dev/fd/5)

And now the exit code is wrong. Is it 0 while it should be 1. I know this is somewhat connected to subshell handling but I couldn't figure out how to solve it.

Upvotes: 0

Views: 139

Answers (3)

Ivan
Ivan

Reputation: 7287

Yes it's subshell and pipe, try like this

FF=$(my_function|tee /dev/fd/5; exit $PIPESTATUS)

Upvotes: 0

KamilCuk
KamilCuk

Reputation: 141493

And now the exit code is wrong. Is it 0 while it should be 1

No, your assumption is wrong. Assuming tee succeeded, the exit code should be 0. From the posix shell manual:

If the reserved word ! does not precede the pipeline, the exit status shall be the exit status of the last command specified in the pipeline.

The "last command" in a pipeline is the rightmost command. Because in your case tee exits with 0, the exit status of FF=$(.... | tee) is zero.

how to solve it.

That depends on the behavior you want to achieve. Usually, in bash you may just set -o pipefail to always catch errors.

Upvotes: 1

cis
cis

Reputation: 1377

It seems that simply stating

set -o pipefail

at the beginning of the script file did the trick.

Upvotes: 0

Related Questions