A Script Template and Useful Techniques for ksh Scripts - Update March 2009

A Script Template and Useful Techniques for ksh Scripts - Update 3/2009

by Bernd Schemmer, March 2009

Introduction

This article is an update to the description for the script template for ksh scripts which I published on BigAdmin in 11/2007:

A Script Template and Useful Techniques for ksh Scripts

The version of the script described in that article was 1.22.21 18.09.2007 and since that time I made some changes and additions that might be worth an update for the description.

Purpose

Describe the new features in the template for ksh scripts

Scope

This article only covers the new code written since 12/2007 until version 1.22.34 27.02.2009 of the script template.

Prerequisites

You should read the article A Script Template and Useful Techniques for ksh Scripts before reading this article.

References

A Script Template and Useful Techniques for ksh Scripts:  http://www.sun.com/bigadmin/content/submitted/ksh_script_template.jsp

The source for the function PrintWithTimeStamps is this blog entry:

http://blogs.sun.com/blogfinger/entry/prepend_command_output_lines_with

New features since 12/2007

New variables

The script template now provides the variable __KSH_VERSION; __KSH_VERSION is 88 for ksh88 and 93 for ksh93. Using this variable you can write code that uses specific features of a ksh release.

The script template now automatically creates a pid file:

## __PIDFILE - save the pid of the script in a file
##
__PIDFILE="/tmp/${__SCRIPTNAME%.*}.pid"

New functions

The function PrintWithTimestamp can be used to print the output of any command that writes to STDOUT with timestamps,

e.g.

PrintWithTimestamp iostat 1 5

prints this output

02.28.2009 16:57:24:    tty       lofi1         lofi2         lofi3         lofi4           cpu
02.28.2009 16:57:24:  tin tout kps tps serv  kps tps serv  kps tps serv  kps tps serv   us sy wt id
02.28.2009 16:57:24:    0    7   0   0 1662    0   0 1146    0   0  221    0   0   15    3 30  0 67
02.28.2009 16:57:25:    0  299   0   0    0    0   0    0    0   0    0    0   0    0    0 24  0 76
02.28.2009 16:57:26:    0  101   0   0    0    0   0    0    0   0    0    0   0    0    0 20  0 79
02.28.2009 16:57:27:    0  101   0   0    0    0   0    0    0   0    0    0   0    0    0 19  0 80
02.28.2009 16:57:28:    0  100   0   0    0    0   0    0    0   0    0    0   0    0    1 18  0 81

New signal handlers

You can now define your own signal handlers for the signals HUP, BREAK, TERM, QUIT, USR1, and USR2. Using this feature you can
write scripts that run as daemon and could be controlled via signal commands.

Example:

# define the new signal handlers in the script
# (Note: In this example the handlers only write a message to STDOUT)
##
## --------------------------------------
## sigusr1_function
##
## sample function for a signal handler
##
## usage: will be called by the signal handler
##
## returns:  -
##
##
function sigusr1_function {
  typeset __FUNCTION="sigusr1_function";   ${__FUNCTION_INIT} ;

# only print a message
  echo "This is sigusr1_function"

  return 0
}

## --------------------------------------
## sigusr2_function
##
## sample function for a signal handler
##
## usage: will be called by the signal handler
##
## returns:  -
##
##
function sigusr2_function {
  typeset __FUNCTION="sigusr2_function";   ${__FUNCTION_INIT} ;

# only print a message
  echo "This is sigusr2_function"

  return 0
}

## --------------------------------------
## sighup_function
##
## sample function for a signal handler
##
## usage: will be called by the signal handler
##
## returns:  -
##
##
function sighup_function {
  typeset __FUNCTION="sighup_function";   ${__FUNCTION_INIT} ;

# only print a message
  echo "This is sighup_function"

  return 0
}

## --------------------------------------
## sigint_function
##
## sample function for a signal handler
##
## usage: will be called by the signal handler
##
## returns:  -
##
##
function sigint_function {
  typeset __FUNCTION="sigint_function";   ${__FUNCTION_INIT} ;

# only print a message
  echo "This is sigint_function"

return 0
}


## --------------------------------------
## sigterm_function
##
## sample function for a signal handler
##
## usage: will be called by the signal handler
##
## returns:  -
##
##
function sigterm_function {
  typeset __FUNCTION="sigterm_function";   ${__FUNCTION_INIT} ;

# only print a message
  echo "This is sigterm_function"

  return 0
}


# now install the new signal handlers
#
## __SIGNAL_SIGUSR1_FUNCTION  - name of the function to execute if the signal SIGUSR1 is received
## default signal handling: none
##
  __SIGNAL_SIGUSR1_FUNCTION="sigusr1_function"

## __SIGNAL_SIGUSR2_FUNCTION  - name of the function to execute if the signal SIGUSR2 is received
## default signal handling: none
##
  __SIGNAL_SIGUSR2_FUNCTION="sigusr2_function"

## __SIGNAL_SIGHUP_FUNCTION  - name of the function to execute if the signal SIGHUP is received
## default signal handling: switch the verbose mode on or off
## If a user defined function ends with a return code not equal zero the default
## action fro the SIGHUP signal is not executed.
##
  __SIGNAL_SIGHUP_FUNCTION="sighup_function"

## __SIGNAL_SIGINT_FUNCTION  - name of the function to execute if the signal SIGINT is received
## default signal handling: end the script if __USER_BREAK_ALLOWED is ${__TRUE} else ignore the signal
## If a user defined function ends with a return code not equal zero the default
## action for the SIGINT signal is not executed.
##
  __SIGNAL_SIGINT_FUNCTION="sigint_function"


## __SIGNAL_SIGTERM_FUNCTION  - name of the function to execute if the signal SIGTERM is received
## default signal handling: end the script
## If a user defined function ends with a return code not equal zero the default
## action for the SIGTERM signal is not executed.
##
  __SIGNAL_SIGTERM_FUNCTION="sigterm_function"

## and last add code to run the script in daemon mode
##
  while [ 0 = 0 ] ; do
    sleep 5
    echo "$0 still running (PID is $$) ..."
  done

Now start the script in one window:

$ ./tests.sh
[28.02.2009 17:37:31] tests.sh v0.0.0.1 started on Sat Feb 28 17:37:31 CET 2009
[28.02.2009 17:37:31] No config file ("tests.conf") found (use -C to create a default config file)
[28.02.2009 17:37:31] Using the log file "/var/tmp/tests.LOG"
./tests.sh still running (PID is 19753) ...

And in another session send some signals to the process, e.g.

$ kill -SIGUSR1 19753

$ kill -SIGUSR2 19753

$ kill -SIGINT 19753

The results will be:

./tests.sh still running (PID is 19753) ...
./tests.sh still running (PID is 19753) ...
This is sigusr1_function
./tests.sh still running (PID is 19753) ...
This is sigusr2_function
./tests.sh still running (PID is 19753) ...
./tests.sh still running (PID is 19753) ...
This is sigint_function
[28.02.2009 17:38:12] ERROR: Script aborted by the user via signal BREAK (CTRL-C)
[28.02.2009 17:38:12] The log file used was "/var/tmp/tests.LOG"
[28.02.2009 17:38:12] tests.sh v0.0.0.1 ended on Sat Feb 28 17:38:12 CET 2009.
[28.02.2009 17:38:12] The RC is 252.

Enhanced cleanup routine

In addition to the already implemented cleanup routines that run before the temporary files and directories are deleted (variable __EXITROUTINES) the script template now also supports finish routines that run after the temporary files and directories are deleted (variable __FINISHROUTINES):

## __EXITROUTINES - list of routines that should be executed before the script ends
## Note: These routines are called *before* temp files, temp directories, and temp
## mounts are removed
##
  __EXITROUTINES=""

## __FINISHROUTINES - list of routines that should be executed before the script ends
## Note: These routines are called *after* temp files, temp directories, and temp
## mounts are removed
##
  __FINISHROUTINES=""

Logging

The prefixes for the runtime messages and the warning, info, and error messages are now variable:

## __INFO_PREFIX - prefix for INFO messages printed if __VERBOSE_MODE = ${__TRUE}
## default: "INFO: "
##
  __INFO_PREFIX="${__INFO_PREFIX:-INFO: }"

## __WARNING_PREFIX - prefix for WARNING messages
## default: "WARNING: "
##
  __WARNING_PREFIX="${__WARNING_PREFIX:-WARNING: }"

## __ERROR_PREFIX - prefix for ERROR messages
## default: "ERROR: "
##
  __ERROR_PREFIX="${__ERROR_PREFIX:-ERROR: }"

## __RUNTIME_INFO_PREFIX - prefix for INFO messages of the runtime system
## default: "RUNTIME INFO: "
##
  __RUNTIME_INFO_PREFIX="${__RUNTIME_INFO_PREFIX:-RUNTIME INFO: }"

Debugging

The history file used in debug mode is now configurable:

__DEBUG_HISTFILE="${__DEBUG_HISTFILE:-/tmp/ksh.history.$$}"

Due to the limitations of arrays in ksh88 the internal debugger only works for scripts with less than 4096 lines . The script
now checks the number of lines before calling the debugger.

Download

The current version of the script template can be downloaded here:

http://bnsmb.de/solaris/scriptt.html

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Sign up or Log in to add a comment or watch this page.


The individuals who post here are part of the extended Sun Microsystems community and they might not be employed or in any way formally affiliated with Sun Microsystems. The opinions expressed here are their own, are not necessarily reviewed in advance by anyone but the individual authors, and neither Sun nor any other party necessarily agrees with them.

Copyright 1994-2009 Sun Microsystems, Inc.
Powered by Atlassian Confluence
Sun Guidelines on Public Discourse Privacy Policy Terms of Use Trademarks Site Map Employment Investor Relations Contact