pipefail
grep: ./README.md: No such file or directory
A pipeline only has a single exit code. By default this is the exit code of the last command in the pipeline. This is bad — in production–quality code we want to make sure that every non–zero exit code is either explicitly handled or results in the script failing immediately. Take this script for example:
#!/usr/bin/env bash
# Count main heading words in a markdown document
grep '^# ' ./README.md | wc --words
If there is no README.md file in the current directory this script will succeed: grep
will helpfully report
grep: ./README.md: No such file or directory
but the exit code of the script will be zero. Often you don’t care about this specific error, but what if the error is something more insidious? Consider this script:
#!/usr/bin/env bash
# Dangerous code, do not use!
netstat --listening --numeric --tcp | tail --lines=+3
This should show every listening TCP network service running on the machine. Let’s say it’s also part of a bigger system to report targets for security auditing, so we want to make the output easily processable. There’s no option to omit the two–line header from netstat
output so we use tail
to print only line three onwards.
There’s a bug in this script, but it’s subtle. Like the “curious incident of the dog in the night–time” from Sherlock Holmes the absence of something can indicate a problem. Consider what happens when there is no netstat
command on the system, such as on a minimal installation:
This page is a preview of The newline Guide to Bash Scripting