Capture the exit status in a variable, not $? later
The pipe rule was only half of it. $? is a single slot that every command overwrites, including the harmless one somebody adds months later — a sed that redacts a token out of a log, a rotate, an echoed heading. The command fails, the sed succeeds, and the check reads the sed. Measured both forms with a deliberately failing command and a sed between: the bare $? reported SUCCESS on a command that had failed, while a status captured into rc on the very next line still read 1. So the durable form names it immediately and branches on the name, which survives anyone later inserting a redaction step. That matters most in exactly the scripts that redact a credential before printing a log, because that redaction is the change that looks safest. Same family as the pipe above: a status read one step too late is a status about something else.
This commit is contained in:
parent
c94b3cb4b5
commit
7f59035fb1
1 changed files with 25 additions and 0 deletions
|
|
@ -150,6 +150,31 @@ with **each other**, not with the source. The same shape bit a `git merge` in th
|
|||
instead of piping, or `set -o pipefail` first. If you want short output AND a reliable
|
||||
status, capture to a file and `tail` the file afterwards.
|
||||
|
||||
### And capture the status into a variable, not `$?` later
|
||||
|
||||
`$?` is a single slot that EVERY command overwrites — including the harmless one somebody
|
||||
adds months later for readability. Measured here:
|
||||
|
||||
```sh
|
||||
some_command > log 2>&1
|
||||
sed -n '1p' log # redact a token, rotate the log, echo a heading — anything
|
||||
if [ "$?" -ne 0 ]; then ... # tests SED, not some_command. A failure reads as success.
|
||||
```
|
||||
|
||||
The durable form names it on the very next line, and branches on the name:
|
||||
|
||||
```sh
|
||||
some_command > log 2>&1
|
||||
rc=$? # nothing may come between these two lines
|
||||
sed -n '1p' log # now insert whatever you like
|
||||
if [ "$rc" -ne 0 ]; then tail log; exit 1; fi
|
||||
```
|
||||
|
||||
Both were run: with the `sed` in between, the bare `$?` reported success on a command that
|
||||
had failed; `rc` still read 1. This is the same family as the pipe above — a status you read
|
||||
one step too late is a status about something else — and it matters most in exactly the
|
||||
scripts that redact a token before printing a log, because that redaction looks harmless.
|
||||
|
||||
## Landing on main: the shape of the lock
|
||||
|
||||
`main` is shared and serialized by `main-capture`. The ordering is load-bearing and BOTH
|
||||
|
|
|
|||
Loading…
Reference in a new issue