Last active
April 26, 2018 17:49
-
-
Save vguarnaccia/6065d725e50f772bd940a174e1b87594 to your computer and use it in GitHub Desktop.
Skeleton of a shell script.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/sh | |
readonly -p VERSION=0.1.0 | |
############################################################################## | |
# This is an example shell script. I do my best to avoid bashisms when it is | |
# not too much of a pain to do so. I also try to stick to a 80 char line limit | |
# and indent with tabs since tabs are easier to work with in `sh` than spaces. | |
# If your script contains calculations or complex logic, please consider | |
# writting it in a modern scripting language such as python. | |
# Inspired by https://dev.to/thiht/shell-scripts-matter and | |
# http://redsymbol.net/articles/unofficial-bash-strict-mode/#issues-and-solutions | |
# Make sure to lint with `shfmt -w example.sh && shellcheck example.sh` | |
# You learn more about shellcheck rules on the wiki. | |
# https://github.com/koalaman/shellcheck/wiki | |
# Lint with `$ shfmt -w example.sh && shellcheck example.sh` | |
# Test scripts with shunit2 and put in version control. | |
############################################################################## | |
# Debug with `$ sh -x example.sh` | |
set -euo pipefail # stop if any failures | |
# Do not accept spaces as Internal Field Separator. | |
# Equivalent to IFS=$'\t\n' in Bash. | |
# Also, use `$@` instead of `$*` | |
safe_IFS="$(printf '%b_' '\t\n')" | |
IFS="${safe_IFS%_}" # protect trailing \n | |
############################################################################## | |
# Helper functions. | |
info() { | |
if [ "$VERBOSE" -gt 0 ]; then | |
echo "[INFO] " "$@" | tee -a "$LOG_FILE" >&2 | |
else | |
echo "[INFO] " "$@" >>"$LOG_FILE" | |
fi | |
} | |
error() { | |
echo "[ERROR] " "$@" | tee -a "$LOG_FILE" >&2 | |
exit 1 | |
} | |
heredoc() { | |
cat <<-EOM | |
Usage: | |
This is an example template of a shell script. It reads | |
parameters from the command line and prints them when run verbosely. | |
Example: | |
./example.sh -p $PWD/file.txt | |
EOM | |
} | |
############################################################################## | |
# Define variables here. | |
# Make sure to source secrets from a `.env` instead of passing secrets though | |
# you may need allow unbound variables when sourcing other people's scripts. | |
# `$ . example_secrets.env # OK!` | |
# `$ set +u; . functions.sh; set -u # allow badness in sourc'ed scripts.` | |
tmp_dir=$(mktemp -d) | |
export tmp_dir | |
# Make sure to release any resources we acquired. | |
tear_down() { | |
# sudo systemctl restart important.service | |
rm -rf "$tmp_dir" | |
} | |
############################################################################## | |
# Parse command line arguments. | |
# Switch statement (slightly) adapted from | |
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash/14203146#14203146 | |
VERBOSE=0 | |
LOG_FILE="/tmp/$(basename "$0").log" | |
while [ $# -gt 0 ]; do | |
key="$1" | |
case $key in | |
-V | --version) | |
echo Version: "$VERSION" | |
shift | |
exit 0 | |
;; | |
-h | --help) | |
heredoc | |
exit 0 | |
shift | |
;; | |
-p | --positional) | |
POSITIONAL="$2" | |
shift # past argument | |
shift # past value | |
;; | |
-o | --optional) | |
OPTIONAL="$2" | |
shift # past argument | |
shift # past value | |
;; | |
--flag) | |
FLAG='YES' | |
shift # past argument | |
;; | |
--nolog) | |
LOG_FILE=/dev/null | |
shift | |
;; | |
-v | --verbose) | |
VERBOSE=1 | |
shift | |
;; | |
*) | |
error "$1 is not a valid option." | |
shift | |
;; | |
esac | |
done | |
readonly -p POSITIONAL | |
readonly -p OPTIONAL="${OPTIONAL:-default value}" # set default | |
readonly -p FLAG="${FLAG:-NO}" | |
readonly -p LOG_FILE | |
readonly -p VERBOSE | |
# Write your functions here. | |
main() { | |
info The positional value is = "${POSITIONAL}" | |
info The optional argument is = "${OPTIONAL}" | |
info The flag is = "${FLAG}" | |
} | |
############################################################################## | |
date >>"$LOG_FILE" | |
date +"%Y-%m-%dT%H:%M:%S%z" >>"$LOG_FILE" | |
main | |
trap tear_down EXIT # Always call tear_down |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment