bash_shell

Automate everything (practical uses of Bash part 1)

I find that having a bias towards automation makes life a lot easier. I’ve been writing more and more scripts the farther along I go in my career. The time it takes to write a little script is hardly anything compared to the time it saves. I just can’t stay comfortable with typing long commands anymore. There’s a certain point where it just makes sense to script a task and that point usually comes only the second or third time I do it.

Usually I write scripts in Bash. Whether I’m on my mac or on my linux box, Bash is there.

So what are some practical uses of Bash? Here’s a few.

Command line arguments
I don’t like having to type tail -f /usr/local/tomcat/logs/webapp.log so I just make a quick bash script that replaces the filename with the webapp whose log I want to tail. I pass it in as a command line argument which bash just refers to as $1.

taillog.sh

#!/bin/bash
tail -F /usr/local/tomcat/logs/$1.log

I probably also alias it:

$ alias taillog=/where/I/store/my/scripts/taillog.sh

Then I can use it like:

$ taillog webapp

Seems like a really subtle difference but the improvement in actual day-to-day development is surprising.

Check if a file or directory exists
I often want to know if a file or directory exists before performing an action. For example, if you pass a non-existent file name to the preceding script it will print out a message and then hang there until you hit Ctrl+C.

$ taillog notexists
tail: cannot open ‘/usr/local/tomcat/logs/notexists.log’ for reading: No such file or directory
^C $ 

It should be updated using an if statement with the -f flag to check that the file exists:

#!/bin/bash
file=/usr/local/tomcat/logs/$1.log
if [ ! -f "$file" ]; then
  echo "The file $file doesn't exist"
  exit 1
fi

tail -F $file

The -d flag is used similarly. For example, I don’t know why you’d want to but, you can check if you have a home directory

checkhome.sh

#!/bin/bash
if [ -d "$HOME" ]; then
  echo "Checks out: you have a home directory at $HOME"
fi

Wait for something
If I want to, for example, restart Tomcat, and wait until my app is up and healthy, I might write a script like this:

#!/bin/bash
# restart tomcat in the background
sudo systemctl restart tomcat &

# wait until health URL is up
while [ ! "$(curl -s http://localhost:8080/health)" ]; do
  echo -n "."
  sleep 1
done
curl -s http://localhost:8080/health

The first trick here is that the ampersand (&) character can be put on the end of any line to make it execute in the background.

The second trick is constructing a loop where we output one period and then sleep one second, as long as there’s no output from the curl command against our health check URL. The -s flag on curl is really important here because without it curl outputs something like the below:

curl: (6) Could not resolve host: localhost; Name or service not known

Obviously we want to be able to check the condition that nothing is output until the actual response comes back, so the -s flag helpfully does that for us.

OK that’s enough for today. I’ll pass along some other practical uses of Bash another time.

Leave a Reply

Your email address will not be published. Required fields are marked *