This is our third installment of the best(ish) series. In this installment we will look at some basic logging functions that simplify life. Here is the code so far.

<code>#!/bin/bash
# Copy some files

# Print usage information and exit
print_usage(){
    echo -e "\n" \
    "usage: ./copy_stuff -s sourcedir -d destdir \n" \
    "\n" \
    "-s <sourcedir> source directory\n" \
    "-d <destdir>   destination directory\n" \
    "-h             this help\n" \
    "\n" && exit 1
}

###
# Options
###

# Loop through $@ to find flags
while getopts ":hs:d:" FLAG; do
    case "${FLAG}" in
        s) # Our source
            SOURCE="${OPTARG}" ;;
        d) # Our destination
            DEST="${OPTARG}" ;;
        h) # Print usage information
            HELP=1;;
        [:?]) # Print usage information
            print_usage;;
    esac
done

###
# Functions
###

log_date(){
    echo $(date +"%b %e %T")
}

error() {
    NOW=$(log_date)
    echo "${NOW}: ERROR: $1"
    exit 1
}

warning() {
    NOW=$(log_date)
    echo "${NOW}: WARNING: $1"
}

info() {
    NOW=$(log_date)
    echo "${NOW}: INFO: $1"
}

# Copy some files from one place to another
copy_files(){
    info "Copying ${SOURCE}/foo to ${DEST}/foo"
    info "Copying ${SOURCE}/bar to ${DEST}/bar"
    info "Copying ${SOURCE}/baz/foo to ${DEST}/baz/foo"
    info "Copying ${SOURCE}/baz/bar/foo to ${DEST}/baz/bar/foo"
    info "Copying ${SOURCE}/dir/somefile to ${DEST}/dir/someotherfile"
    echo
}

# Restart some service
restart_service(){
    info "Stopping the service"
    info "Making sure the service is stopped"
    info "Reticulating splines..."
    warning "splines not reticulated"
    info "Starting the service"
    echo
}

# Test to see if the service is running
test_service(){
    info "service is tested"
}

###
# Program execution
###

[ "${HELP}" ] && print_usage

if [ ${SOURCE} ] && [ ${DEST} ]
then
    info "Copying files from ${SOURCE} to ${DEST}"
    copy_files
    info "Restarting the service"
    restart_service
    info "Testing the service"
    test_service
fi
</code>

Lets break it down…

<code>log_date(){
    echo $(date +"%b %e %T")
}

error() {
    NOW=$(log_date)
    echo "${NOW}: ERROR: $1"
    exit 1
}

warning() {
    NOW=$(log_date)
    echo "${NOW}: WARNING: $1"
}

info() {
    NOW=$(log_date)
    echo "${NOW}: INFO: $1"
}
</code>

We have some new friends in the form of error,warning and info. These functions simply tag some provided text with an indicator of the type of output and also provide timestamp information. They save us just enough time to prove useful as we will see in a moment.

<code>    info "Reticulating splines..."
    warning "splines not reticulated"
</code>

You can see here that all we have to do is specify the logger we want to use and the particular output.

Let’s see it run.

<code># ./copy_stuff -s /dir1 -d /dir2
Mar 9 09:16:00: INFO: Copying files from /dir1 to /dir2
Mar 9 09:16:00: INFO: Copying /dir1/foo to /dir2/foo
Mar 9 09:16:01: INFO: Copying /dir1/bar to /dir2/bar
Mar 9 09:16:01: INFO: Copying /dir1/baz/foo to /dir2/baz/foo
Mar 9 09:16:01: INFO: Copying /dir1/baz/bar/foo to /dir2/baz/bar/foo
Mar 9 09:16:01: INFO: Copying /dir1/dir/somefile to /dir2/dir/someotherfile

Mar 9 09:16:01: INFO: Restarting the service
Mar 9 09:16:01: INFO: Stopping the service
Mar 9 09:16:01: INFO: Making sure the service is stopped
Mar 9 09:16:01: INFO: Reticulating splines...
Mar 9 09:16:01: WARNING: splines not reticulated
Mar 9 09:16:01: INFO: Starting the service

Mar 9 09:16:01: INFO: Testing the service
Mar 9 09:16:01: INFO: service is tested
</code>

Nice output. It is also worth noting that now you can simply change the functions to modify all of the output of your script. This might be useful if you wanted to change the date format for instance.

For more information on date formatting see http://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/

Bash Best(ish) practices part 4 Bash Best(ish) practices part 2 Bash Best(ish) practices part 1