Shell Script Guidelines

Software

We write scripts for bash and bash only.

Script Preamble

Any shell script should always start with the following preamble

# $Id$
#
# Author: <author name>
# Date:   <creation date>
#
# Short purpose description.
#
# USAGE:
# Detailed usage information goes here. Behavior and command line 
# switches etc
#

doms_env.sh

The DOMS project includes a file bin/doms_env.sh defining basic functions and varibles useful for scripts. A short overview:

To include doms_env.sh in your scripts simply source it in:

source doms_env.sh

To distribute it in your packages simply include a copy in your setup. This is not an ideal solution, but is acceptable since the script is really simple and not likely to receive many updates

Code Style

Indentation

We use 4 white spaces for indentation. Comment strings have one space after the # like in the preamble above.

Function Documentation

Functions are documented like so

#
# This function is really cool.
# You should try it!
#
function brew_coffee () {
  # FIXME: Implement me
}

With extra comment lines in top an bottom of the documentation.

Literals and Variable Naming

Avoid hardcoded literals where ever it makes sense (as you would in Java code too). Variables should have short descriptive to-the-point names.

Do not

echo "Hello world" > my_file.txt
scp my_file.txt mikkel@pc134.sb:/~

but do

MY_FILE="my_file.txt"
REMOTE="mikkel@pc134.sb:/~"

echo "Hello world" > $MY_FILE
scp $MY_FILE $REMOTE

Inline Invocations

We use $(command) instead of backpings ` for running inlined commands. For example

FILE=$HOME/my_file.xml
NAME=$(basename $FILE .xml)

Workflow

Factor you control flow into well-named and documented functions and invoke them from a Workflow section in the bottom of the script. This make it easy to change the workflow or do partial runs by commenting out lines. Fx:

#
# Roll a tarball containing all sensitive files and store the
# absolute file path in $BACKUP_FILE
#
function create_backup () {
    # code goes here
}

#
# Upload $BACKUP_FILE to $BACKUP_SERVER
#
function upload_backup () {
    # code goes here
}

#
# Workflow
#
create_backup
upload_backup

Fail on Errors

Exit gracefully with a message on stderr if an error occur. You should check for errors after any command that might cause errors. Fx

scp $FOO $BAR
if [ "$?" != "0" ]; then
    echo "Failed to copy $FOO to $BAR. Bailing out." 1>&2
    exit 1
fi;

or by using doms_env.sh:

scp $FOO $BAR
fail_on_error "Failed to copy $FOO to $BAR. scp exited with $?"

Working Directory

Scripts should be working-directory-independent, meaning that they do the same thing no matter what working directory they are invoked from. Ie. both these invocations should do the same:

mikkel@pc134:~/Applications/Summa$ start-server.sh &
mikkel@pc134:~/$ Applications/Summa/start-server.sh &

If you need to change the working directory to that of the script file do it like this

DEPLOY=$(dirname $0)
pushd $DEPLOY > /dev/null

#
# Main script body
#

popd > /dev/null

Never Background

You scripts should never background unless explicitly instructed to. Ie. don't end them with

my_long_running_command &

Clean Backgrounding

If you have run something in the background run it with setsid, like this

setsid long_running_command > long_command.log

This will run the command in a different session and ensure that it does not exit even if the parent session crashes.

Hints

IDEA is horrible for editing shell scripts. GEdit bundled with Gnome (also just called "Text Editor") has nice syntax highlighting for shell scripts.

Script Guidelines (last edited 2010-03-17 13:12:57 by localhost)