4 ms·
Protip: die() { echo "$@" >&2; exit 1; } wget --quiet --output-document /usr/local/bin/mybinary "$download_url" || die 'Failed downloading the CLI'
by waterhouse 6y ago
Protip:
die() { echo "$@" >&2; exit 1; }
wget --quiet --output-document /usr/local/bin/mybinary "$download_url" ||
die 'Failed downloading the CLI'
chmod +x /usr/local/bin/mybinary ||
die 'Failed making CLI executable'
If you need more complex cleanup, that doesn't work as well... but (a) hopefully you can avoid that cleanup and just use a plain "|| die", and (b) if you need cleanup, hopefully you can put that into one function (possibly "die" itself) and have its cleanup work no matter where it's called from, and still run everything as "|| cleanup_and_die" or whatever you'd call it.
- neves 6y agoproprotip: in the beginning of your scripts put: set -e # stop script if error set -u # stop with undefined var set -o pipefail # stop with pipe fail Now your scripts will have a sane default behavior
- wahern 6y agoPro-protip: don't use echo. # panic STRING-FORMAT [...] # # write printf-formatted message to stderr, prepending # script name, and exit failure panic() { printf "%s: %.0s${1}\n" "${0##*/}" "$@" >&2 exit 1 } Prepending the script name is immensely helpful when diagnostic messages are mixed on stderr. It's also standard style for Unix utilities in general. The BSD extensions err(3) and warn(3), provided by all modern Unix libc implementations and commonly use by shell utilities, prepend the program name. Another common style guideline is to include context for the diagnostic, often prepended. For example, wget --quiet --output-document /usr/local/bin/mybinary "$download_url" \ || panic '%s: unable to download' "$download_url"
- cat199 6y agowhy is printf preferable to echo here other than formatting?
- deleted 6y ago[deleted]
- stonewareslord 6y agoEcho is defined differently in different shells ("not portable"). Also it can have arguments which breaks things sometimes: echo Option -n invalid # OK echo -n is not valid # Uh oh printf '%s ' -n is not valid # Always okay Generally you should use printf because of its consistency. For a simpler example of OP's: panic() { printf '%s\n' "${0}: ${*}"; exit 1; } Is fine. I don't see the need to pass a format string to your function. Just call: panic "${download_url}: unable to download"
- hctaw 6y agoI'll use what I can read. I can't parse that at a glance, and won't use it. The real pro tip is: don't use bash if it's not trivial to read
- wahern 6y agoIt's not Bash. I purposefully stick to POSIX shell constructs because memorizing all the various Bash (and ksh and Zsh) extensions and their oddball semantics is too much trouble. By sticking to POSIX shell it's easier to learn and remember actual shell programming semantics--parameter expansion, positional parameters, pathname globbing, etc. You have to understand those things, anyhow, if you actually care to understand the language; they happen whether you know it or not, and they're fundamental to the language. Plus, the POSIX specification for the shell is significantly more concise and clear than the manuals for Bash, Zsh, etc. See Shell & Utilities -> Shell Command Language at https://pubs.opengroup.org/onlinepubs/9699919799/ https://pubs.opengroup.org/onlinepubs/9699919799/ I know exactly where to go if I can't remember the difference between ${foo:-X} vs ${foo+Y}.
- 0xbadcafebee 6y agoPro-protip tip: Add $0 but don't do pattern expansion. Worst case it's just slightly more verbose output. Best case, it's simpler to understand & maintain, and showing the path to your script will help unfamiliar people locate it quicker for debugging. (& I think it looks cleaner) Also, don't run a command that directly overwrites a file unless you know it's going to succeed. A temp file lets you atomically replace the file only if the download succeeded. And a cleanup trap helps clean this up in the event of errors. Finally, you can die on unset variables or errors (cleanup still works) and you can enable tracing if environment variable DEBUG=1 was set. #!/usr/bin/env sh set -eu [ "${DEBUG:-0}" = "1" ] && set -x cleanup() { rm -f /usr/local/bin/mybinary.tmp ; } ; trap cleanup EXIT panic() { printf "$0: Error: %s\n" "$1" >&2; exit 1; } mkdir -p /usr/local/bin [ -e /usr/local/bin/mybinary ] || \ wget -q -O /usr/local/bin/mybinary.tmp "$url" \ || panic "wget was unable to download '$url'" mv -f /usr/local/bin/mybinary.tmp /usr/local/bin/mybinary
- srswtf123 6y agoUse logger and push your messages to syslog, and aggregate using your favorite tool. https://linux.die.net/man/1/logger https://linux.die.net/man/1/logger