These examples were compiled from Best Practices for Writing Bash Scripts and Use the Unofficial Bash Strict Mode (Unless You Looove Debugging).
Another resource of note: Bash 3 Boilerplate.
As a single snippet, start your bash script with:
set -euo pipefail
set -e or -o errexit - exit when a command fails Add the following at the start of your script. It will make the script exit when a command fails.
set -e
set -u or -o nounset - exit when trying to use undefined variable Add the following at the start of your script. It will make the script exit when attempting to use an undefined variable.
set -u
set -o pipefail - return the exit code of piped commands that error Add the following at the start of your script.
It will return the exit code of the last command to exit with a non-zero status code (ie. error).
set -o pipefail
Debug with set -x or -o xtrace Add the following to print out each commans befoee it’s executed.
set -x
if [ ! -f ./pdfgen/pdfgen ]; then
echo "Building pdfgen binary"
npm run --prefix pdfgen build:linux
else
echo "Pdfgen binary already exists, skipping build"
fi
if [ ! -L /usr/local/bin/heroku ];
then
wget https://cli-assets.heroku.com/branches/stable/heroku-linux-amd64.tar.gz
sudo mkdir -p /usr/local/lib /usr/local/bin
sudo tar -xvzf heroku-linux-amd64.tar.gz -C /usr/local/lib
sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku
fi
# long
if [[ -z "${CIRCLE_BRANCH}"] ]; then
npm run redis-cli flushall
fi
npm run sync
# one-liner
[-z "${CIRCLE_BRANCH}"] && npm run redis-cli flushall; npm run sync
case $CIRCLE_BRANCH in
"develop")
export ENVIRONMENT="dev"
export HEROKU_APP=dev-app
;;
"staging")
export ENVIRONMENT="staging"
export HEROKU_APP=staging-app
;;
"production")
export ENVIRONMENT="production"
export HEROKU_APP=production-app
;;
esac
read -p "Are you sure you want to merge 'develop' into 'staging'? (y/N)" -n 1 -r
echo # we like having a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
git merge develop --ff-only
git push
fi
A final bit of advice, if it’s more than a couple of lines, try to use something like JavaScript, or Python to write your script.
I’ve got some resources to do that in modern JavaScript/Node:
- ES6 by example: a module/CLI to wait for Postgres in docker-compose
- How to make beautiful, simple CLI apps with Node
We’ve got .env
files laying around, Docker Compose deals with this for use usually but say we want to get something running outside of Docker (and without using something like dotenv).
Here’s the snippet for a *NIX shell:
export $(cat .env | xargs)