Shell script common template

This is the header of my script shell template (which can be found here: http://www.uxora.com/unix/shell-script/18-shell-script-template).

It is a man look alike which is used to by usage() to diplsay help as well.

#!/bin/ksh
#================================================================
# HEADER
#================================================================
#% SYNOPSIS
#+    ${SCRIPT_NAME} [-hv] [-o[file]] args ...
#%
#% DESCRIPTION
#%    This is a script template
#%    to start any good shell script.
#%
#% OPTIONS
#%    -o [file], --output=[file]    Set log file (default=/dev/null)
#%                                  use DEFAULT keyword to autoname file
#%                                  The default value is /dev/null.
#%    -t, --timelog                 Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
#%    -x, --ignorelock              Ignore if lock file exists
#%    -h, --help                    Print this help
#%    -v, --version                 Print script information
#%
#% EXAMPLES
#%    ${SCRIPT_NAME} -o DEFAULT arg1 arg2
#%
#================================================================
#- IMPLEMENTATION
#-    version         ${SCRIPT_NAME} (www.uxora.com) 0.0.4
#-    author          Michel VONGVILAY
#-    copyright       Copyright (c) http://www.uxora.com
#-    license         GNU General Public License
#-    script_id       12345
#-
#================================================================
#  HISTORY
#     2015/03/01 : mvongvilay : Script creation
#     2015/04/01 : mvongvilay : Add long options and improvements
# 
#================================================================
#  DEBUG OPTION
#    set -n  # Uncomment to check your syntax, without execution.
#    set -x  # Uncomment to debug this shell script
#
#================================================================
# END_OF_HEADER
#================================================================

And here is the usage functions to go with:

  #== needed variables ==#
SCRIPT_HEADSIZE=$(head -200 ${0} |grep -n "^# END_OF_HEADER" | cut -f1 -d:)
SCRIPT_NAME="$(basename ${0})"

  #== usage functions ==#
usage() { printf "Usage: "; head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#+" | sed -e "s/^#+[ ]*//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
usagefull() { head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#[%+-]" | sed -e "s/^#[%+-]//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
scriptinfo() { head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#-" | sed -e "s/^#-//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g"; }

Here is what you should obtain:

# Display help
$ ./template.sh --help

    SYNOPSIS
    template.sh [-hv] [-o[file]] args ...

    DESCRIPTION
    This is a script template
    to start any good shell script.

    OPTIONS
    -o [file], --output=[file]    Set log file (default=/dev/null)
                                  use DEFAULT keyword to autoname file
                                  The default value is /dev/null.
    -t, --timelog                 Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
    -x, --ignorelock              Ignore if lock file exists
    -h, --help                    Print this help
    -v, --version                 Print script information

    EXAMPLES
    template.sh -o DEFAULT arg1 arg2

    IMPLEMENTATION
    version         template.sh (www.uxora.com) 0.0.4
    author          Michel VONGVILAY
    copyright       Copyright (c) http://www.uxora.com
    license         GNU General Public License
    script_id       12345

# Display version info
$ ./template.sh -v

    IMPLEMENTATION
    version         template.sh (www.uxora.com) 0.0.4
    author          Michel VONGVILAY
    copyright       Copyright (c) http://www.uxora.com
    license         GNU General Public License
    script_id       12345

You can get the full script template here: http://www.uxora.com/unix/shell-script/18-shell-script-template


I would steer clear of relying on bash as the shell and model your solution on top of shell syntax defined by POSIX and use /bin/sh on the shebang. We had a number of surprises recently when Ubuntu changed /bin/sh to dash.

Another pandemic in the shell world is a general misunderstanding of exit status codes. Exiting with an understandable code is what lets other shell scripts programmatically react to specific failures. Unfortunately, there is not a lot of guidance on this beyond the "sysexits.h" header file.

If you are looking for more information about good shell scripting practices, concentrate on Korn shell scripting resources. Ksh programming tends to focus on really programming as opposed to writing haphazard scripts.

Personally, I haven't found much use for shell templates. The unfortunate truth is that most engineers will simply copy and paste your template and continue to write the same sloppy shell code. A better approach is to create a library of shell functions with well-defined semantics and then convince others to use them. This approach will also help with change control. For example, if you find a defect in a template, then every script that was based on it is broken and would require modifications. Using a library makes it possible to fix defects in one place.

Welcome to the world of shell scripting. Writing shell scripts is a bit of a lost art that seems to be entering a renaissance. There were some good books written on the subject in the late 90's - UNIX Shell Programming by Burns and Arthur comes to mind though the Amazon reviews for the book make it seem awful. IMHO, effective shell code embraces the UNIX philosophy as described by Eric S. Raymond in The Art of Unix Programming.

Tags:

Shell

Bash