( make 2>&1 | tee make.log && exit $PIPESTATUS ) &&

Could someone give me a detailed explanation of the above line? I know that tee is creating a text file while also allawing the output to come to the screen but need a better understanding of $PIPESTATUS. Is "exit" exiting everything to the left of it or $PIPESTATUS to the right? Why are there two sets of "&&"? And I'M sure the variable $? comes it to play somewhere here. Thanks.

Dani AI

Generated

Short answer: the line runs your build in a subshell, pipes its output through tee, and then uses Bash's PIPESTATUS array to control what the subshell returns — which in turn makes the outer && decide whether the next command runs.

Clarification and why it’s written that way (answers to and ):

  • Parentheses create a subshell, so exit inside them only exits the subshell, not your interactive shell or script. That lets the subshell return a specific status to the outer shell without killing the whole process.
  • && is the usual logical AND. The inner && (inside the parentheses) conditions the exit on the pipeline’s return value; the outer && is chaining whatever comes after the subshell to run only if the subshell itself returned zero.
  • $? is just the last command’s status (for a pipeline without pipefail that is the last command in the pipeline, e.g. tee). PIPESTATUS is a Bash-only array that contains the exit codes of each stage in the last pipeline; use ${PIPESTATUS[0]} for the first command, ${PIPESTATUS[1]} for the second, and ${PIPESTATUS[@]} to see them all.

Safer/clearer patterns (examples)

  • Prefer set -o pipefail if you want the pipeline to fail when any stage fails:

    set -o pipefail
    build_tool 2>&1 | tee build.log
    rc=$?
  • If you need the specific exit code of the first stage (no pipefail), capture it explicitly right after the pipeline:

    build_tool 2>&1 | tee build.log
    rc_build=${PIPESTATUS[0]}
    rc_tee=${PIPESTATUS[1]}

Practical notes and cautions

  • Use ${PIPESTATUS[0]} rather than the bare $PIPESTATUS for clarity (bare form expands to the first element but is cryptic).
  • PIPESTATUS and set -o pipefail are Bash extensions — not portable to plain POSIX sh on all systems.
  • Exit codes are modulo 256; values above 255 are truncated.
  • If you want the subshell to always return the original command’s status, use ; exit ${PIPESTATUS[0]} (semicolon) instead of && exit ..., because && will only run exit when the pipeline succeeded (i.e. the last stage returned 0).

$PIPESTATUS is an environment variable that holds the return values from any single, or chained commands in an array.... The page here should explain it far better than I can!:

The && is a logical/boolean AND, similar to C, C++, Java etc.
As far as I understand it, the && inside the braces is part of the compound, boolean expression based on the commands contained in the braces. The && at the end of the line means that the next command (or line) in the bash script will only be executed if the commands to the left of the && (so basically if everything inside the braces) succeeds. So the next line or command in the shell script is the right hand part of the AND at the end of the code you've posted.

So it's kinda like:
If (make 2>&1 OR tee make.log AND exit $PIPESTATUS) AND NextLineOrCommand.....

So it's just a way of conditionally chaining several commands together.
At least I think that's the way it works!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.