Simple Bash Scripts for Lazy People | Part 3: Other Examples

This is part 3 of a five-part series:

  • Part One has examples for common daily tasks in Git.
  • Part Two, similar examples for Rails.
  • Part Three, miscellaneous cases.
  • Part Four dissects an example of a failed attempt at a useful script.
  • Part Five concludes with a brief discussion of when to use Bash as opposed to some other scripting language.

TL;DR for Part 3:

  • Use environment variables to make a script portable
  • Using ssh with -- to pass a string of commands to execute is great for working with remote systems
  • Know how to use SSH keys

Apache

Some projects aren’t Rails projects. Some are PHP and run on an Apache server. Since you have all your non-sensitive configurations (like rewrite rules) in version control (you do, right? … right?), you need an easy way for devs to start and stop their web server with those configurations.

These scripts doesn’t live in ~/bin but rather in a bin directory in the project root.

bin/devctl

#!/bin/bash
if [[ -z "$1" ]]; then
  echo "argument of stop, start, or restart required";
  exit 1
fi

DEVROOT=$(pwd) \
PHP_SO_LOCATION="/usr/local/Cellar/php56/5.6.30_6/libexec/apache2/libphp5.so" \
  apachectl -f "$(pwd)/conf/httpd.conf.dev" -k "$1"

That file’s real name is bin/devctl_example. There’s a .gitignore entry for bin/devctl (just like with your rails database.yml and secrets.yml files; then you could use something like link-configs from Part 2 to manage this).

Anything in the config that might be variable among devs’ environments should be extracted to an environment variable so the script is portable.

The httpd.conf.dev gets the values for DEVROOT and PHP_SO_LOCATION from the environment for lines like

DocumentRoot "${DEVROOT}"

and

LoadModule php5_module ${PHP_SO_LOCATION}.

bin/push-staging

For some projects, deploying is just a matter of pulling down the latest code and restarting Apache. I have scripts like these (and similar scripts for production and other pre-production runways).

#!/bin/bash
git push && ssh deploy-user@staging-host -- 'cd /var/www/html/web-root
  && git branch
  && git pull
  && sudo apache2ctl restart'

Being able to pass a command as a string after -- with ssh is handy for automating a lot of tasks. In this case I’m including git branch with that list of commands so that I can confirm from the output what branch it’s pulling.

There’s no backslash to continue the lines because the newlines get squashed when the string is sent to the remote system.

Scripts like these are also helpful for projects where we’re collaborating with a client who’s comfortable making markup, style, and even some code changes, but isn’t ready to do their own deploys. We can give them this with simple git pull and git commit instructions and say “Then run the bin/push-staging script to deploy your changes” (after adding their public ssh key to the deploy-user’s authorized_keys).

Multiple Versions of a Server

Since we work with many different clients at beezwax, we might need multiple versions of a given database in our development environments. Differences of even minor versions can mean a big difference in functionality (e.g. the introduction of the jsonb datatype and its associated functions and operators in Postgres 9.4 and 9.5).

So I have two (similar but not identical) scripts for managing different Postgres servers:

postgres-9.3

#!/bin/bash
cmd="$1";
/usr/local/opt/postgresql-9.3/bin/pg_ctl -D /opt/postgresql-9-3-data "$cmd";

and

postgres-9.5

#!/bin/bash
cmd="$1";
"$POSTGRES/bin/pg_ctl" -D "$PGDATA" "$cmd";

The 9.5 script uses the $POSTGRES and $PGDATA env vars set in my .bash_profile, while the 9.3 script hardcodes those locations. This makes it easy to stop and start the different versions:

$ postgres-9.3 start
server starting
LOG: database system was shut down at 2018-06-04 13:47:44 PDT
LOG: MultiXact member wraparound protections are now enabled
LOG: autovacuum launcher started
LOG: database system is ready to accept connections

$ postgres-9.5 start
server starting
LOG: database system was shut down at 2018-06-04 13:47:55 PDT
LOG: MultiXact member wraparound protections are now enabled
LOG: autovacuum launcher started
LOG: database system is ready to accept connections

$ postgres-9.3 stop
LOG: received smart shutdown request
LOG: autovacuum launcher shutting down
LOG: shutting down
waiting for server to shut down....LOG: database system is shut down
done
server stopped

Similarly with the psql clients, the psql in /usr/local/bin is a symlink to the 9.5 version. I have an alias psql93 for the 9.3 client.

On to Part 4: Cadaver Dissection

Leave a Reply