bash in production projects

During my time as a Support Engineer at Travis CI, I helped customers to diagnose issues with their on-prem installation of Travis CI, wrote documentation, and worked with the product team on feature requests.
Here and there, I helped the engineers with some development work as well. Interestingly, I wasn’t writing that much Ruby (Travis CI is mostly built with Ruby) but Bash instead.

Travis CI Enterprise is the on-prem version of Travis CI, installed on your own servers. The installers for all components, to my surprise, were just Bash scripts. When I had joined the company, I was frightened of longer Bash scripts, because I wasn’t able to grok what was going on there.

Interestingly, most of our internal build tools were also written in Bash. When I peeked into those files, I was surprised by how readable they were.
Eventually, we needed to update one of our install scripts so that customers could install on newer Ubuntu machines (before we only supported Ubuntu 14.04). The other engineers were all busy with bug fixes and feature work on the main product, so I took the initiative and started to hack away.

With our internal build tools as a reference, I got to work on a brand-new installer. Writing Bash code, in the end, wasn’t too tricky, as it has functions, variables, and for-loops.
I spent two days to develop this new installer and had a blast writing the code.

What I learned

Here and there, I needed to work with JSON files. Ruby, Python, and friends have builtin support for JSON, Bash doesn’t. But there’s a convenient command-line tool: jq. It allows to query a JSON file, write JSON into a file, and so much more. Today, this is one of the most essential tools I use.

Bash in Production

Bash has a lot of gotchas. Initially, I was afraid of shipping code that’d pose security risks or just wasn’t safe.
One of my colleagues recommended shellcheck to me. shellcheck is a linter (like ESLint) that helps to discover potentially unsafe Bash Code. I installed a Visual Studio Code extension to see issues right away. Additionally, I added it to the CI workflow so that no unsafe code would get into production.

Installing Docker

On your Mac or Windows machine, you download the installer, run it, and done. As it turned out, on Linux, a few more steps were necessary after installing the package.
And installing the package was the easy part. I remember that it took me a few hours at least to find out the difference between daemon.json and systemd config extensions.
As it eventually turned out, using the daemon.json file was the right choice to configure the right storage driver (also a long read to find out the right one) and logging configuration.

This project opened the mental door for me that I can write Bash code that is longer than a few lines and also is safe to run in production. Are you curious to look at the code? Then please click here.

Did you enjoy this article? Follow me on Twitter and tell me what you liked.