DEV Community

loading...
Cover image for Practicing Safe S...hell

Practicing Safe S...hell

Cristian
Rubyist / Software Engineer / GPG: 0x396F5BEE67FD54AD
・2 min read

While creating SkyHole, I found myself writing a few shell scripts. They get the job done, and although I could have written them in a language such as Ruby or Python, it's a safe bet to make that any UNIX machine that execute these scripts have a shell.

As I was writing these scripts, it became clear that out of the box, a shell script doesn't have the niceties that you might expect when coming from another language. Things such as the script exploding when a variable isn't defined or the script exiting when a step in the function has failed aren't handled normally in a shell script. The purpose of this post is to share a few tricks to make scripting in a shell a bit safer.

Have a shebang

Not every machine a script runs on might have an up to date version of bash at /bin/bash. For example, macOS ships with an old version on this path.

#!/usr/bin/env bash
Enter fullscreen mode Exit fullscreen mode

Set the exception parameter

If a script fails at a certain point, what would you like to happen? Most of the time, you want it to stop and not continue because the rest of the script might depend on that command to succeed. You can tell the shell to exit if anything throws an error immediately, and therefore the rest of the script won't continue running.

set -e
Enter fullscreen mode Exit fullscreen mode

If you want to take this a step further, you can add -o pipefail, which protects against any failure anywhere in a pipeline, rather than just the last command.

set -eo pipefail
Enter fullscreen mode Exit fullscreen mode

Set the undefined parameter

A script might rely on user input or data from another source to run correctly. What happens when that data is empty, and a variable never gets set? Nothing. The script will continue and fail only when an empty input is invalid for that command. What about when you interpolate a path? For example:

rm -rf "${USER_FOLDER}/"
Enter fullscreen mode Exit fullscreen mode

What's going to happen here if the variable USER_FOLDER is never set? You guessed it; the shell will interpret that command as rm -rf "/". That would not be very good. You can prevent this from happening by adding the following to the top of your scripts.

set -u
Enter fullscreen mode Exit fullscreen mode

Conclusion

What does this look like all together? I always add these two lines to the top of every shell script I write.

Hint: you can combine multiple set parameters.

#!/usr/bin/env bash

set -euo pipefail
Enter fullscreen mode Exit fullscreen mode

Check out Anybody can write good bash (with a little effort) for more tips and tricks when scripting in shell. It was the inspiration for this post.

Discussion (0)