A backup script runs the pipeline tar cf - /srv | gzip > /backup/srv.tar.gz and then examines $? on the next line. tar exits non-zero because one file could not be read, while gzip compresses what it was given and exits 0. Assuming default shell options, what does $? hold?

LPIC-1 Exam 102-500, objective 105. Shells and shell scripting hard

Machine-checked — no person has signed for it. This question was read against the source cited below by an automated pass, which found no contradiction. That is a weaker claim than it sounds: the same kind of process wrote the question, so it can confirm its own mistake.

Treat it as a good draft rather than as settled fact, and read the source below before you rely on it. It is not used in mock exams here — only questions a person has signed for are.

How these questions are written — where each question comes from, what the verification ledger records, and what happens when one is found wrong.

The options

Correct 0, because the status of a pipeline is the status of its last command

Correct. bash reports the exit status of the rightmost command of a pipeline, which here is gzip. The script therefore concludes that the backup succeeded, and tar's failure goes unnoticed. This is the classic reason a broken backup reports success for months.

Not correct Non-zero, because the status of a pipeline is the status of the first command that failed

Wrong under default options. That behaviour has to be asked for with set -o pipefail, which makes the pipeline return the status of the rightmost command that exited non-zero. Without it, only the last command's status is reported.

Not correct Non-zero, because a pipeline stops as soon as one of its commands fails

Wrong. A pipeline does not abort. All of its commands are started at once and run concurrently in their own subshells, connected by pipes, and the shell waits for all of them before reporting a single status.

Not correct 0, because $? reports whether the shell managed to set the pipeline up, not what the commands did

Wrong reasoning, even though the digit happens to be right. $? is never a report on whether the shell managed to wire the pipeline up; it is always a status that some command produced. A command that does not exist reports 127 when it is run on its own, and inside a pipeline even that number only reaches $? when the missing command is the last member.

Why

By default the return status of a pipeline is the exit status of the last command in it, so a failure anywhere earlier is thrown away. bash offers two ways out. PIPESTATUS is an array holding the status of every member of the most recently executed pipeline, so ${PIPESTATUS[0]} is tar's status and must be read immediately, before the next command overwrites the array. set -o pipefail changes the rule itself, making the pipeline return the status of the rightmost command that failed and zero only when every member succeeded. Note that set -e does not help here on its own: it acts on the pipeline's status, which is the very number that is wrong.

Where this comes from

Cited
manual page bash(1)

Practise this

Reading one question is not practice. The trainer will draw a short set from objective 105 and space the ones you get wrong.

Practise LPIC-1 Exam 102-500

More questions on this objective

All questions on Shells and shell scripting

Practise LPIC-1 Exam 102-500