Created SC3040 (markdown)

Vidar Holen
2021-08-25 17:11:58 -07:00
parent c087904e65
commit 263b926162

45
SC3040.md Normal file

@@ -0,0 +1,45 @@
## In POSIX sh, set option pipefail is undefined.
### Problematic code:
```sh
#!/bin/sh
set -o pipefail
if cmd1 | cmd2 | cmd3
then
echo "Success"
fi
```
### Correct code:
```sh
fail="$(mktemp)"
if { cmd1 || echo > "$fail"; } |
{ cmd2 || echo > "$fail"; } |
cmd3 && [ ! -s "$fail" ]
then
echo "Success"
fi
rm "$fail"
```
or switch to a shell that supports pipefail, such as Bash.
### Rationale:
ShellCheck found `set -o pipefail` in a script declare to run with `sh` or `dash`. This feature may not be supported on these shells.
As an alternative, each stage in the pipeline such as `cmd1` can be rewritten as `{ cmd1 || echo > file; }` which will behave as before but now also write the exit code into `file` if the command fails.
If the file has been written to when the pipeline is done, it means one of the commands failed. This is demonstrated in the correct example.
This can obviously be extended with e.g. `echo "cmd1=$?" >> file` if the particular exit codes for particular commands are desired.
### Exceptions:
If the script has already inspected the current shell and determined the option is available, you can [[ignore]] this message.
### Related resources:
* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!