diff --git a/SC3040.md b/SC3040.md new file mode 100644 index 0000000..450088d --- /dev/null +++ b/SC3040.md @@ -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! \ No newline at end of file