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
#!/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
-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
#!/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.