Skip to content

Instantly share code, notes, and snippets.

@beugley
Created October 1, 2015 16:36
Show Gist options
  • Save beugley/e6f2a8b9011766fd850e to your computer and use it in GitHub Desktop.
Save beugley/e6f2a8b9011766fd850e to your computer and use it in GitHub Desktop.
Shell: runsas.ksh is a wrapper around sasgsub (grid enabled sas) that acts like command line sas
#!/bin/ksh
##############################################################################
## This script is a wrapper around sasgsub. It will:
## 1) run your SAS script and create a combined log/lst file in the
## directory where your script is located.
## 2) Return an error code if your script has an error.
##
## Usage: runsas.ksh script.sas [-b] [sas command-line options]
## Specify the -b switch when invoking from a batch script. That will
## cause the log/lst to be written to stdout. Multiple invocations of this
## script from a single shell script will cause output for all of them to
## be sent serially to stdout, so the calling script should redirect its
## output to a single log file.
##
## Return codes:
## 0: SAS script was executed successfully
## 1: Usage error (invalid/missing arguments)
## 2: sasgsub execution error (SAS script was not executed on a grid)
## 3: Error in SAS script
##############################################################################
USAGE="Usage: runsas.ksh sas_script [-b] [sas options | -gridsasopts <sas_options>] [-gridwork <shared_dirname>] [-gridjobopts <job_options>]"
##
## The command line must have at least one argument, the SAS script name.
##
if (($# < 1))
then
print -u2 $USAGE
exit 1
else
SASSCRIPT=$1
if [[ ! -f $SASSCRIPT ]]
then
print -u2 "ERROR: $SASSCRIPT does not exist!"
exit 1
fi
## Shift the SAS script name out of the argument list.
shift 1
fi
##
## Initialize arguments.
##
BATCH="NO"
ARGVAL_NEXT=""
GRIDWORK=""
GRIDJOBOPTS=""
GRIDSASOPTS=""
##
## Process remaining arguments, if any.
##
for argument in "$@"
do
if [[ "$ARGVAL_NEXT" != "" ]]
then
if [[ "$ARGVAL_NEXT" == "-gridwork" ]]
then
GRIDWORK="$argument"
elif [[ "$ARGVAL_NEXT" == "-gridjobopts" ]]
then
GRIDJOBOPTS="$argument"
elif [[ "$ARGVAL_NEXT" == "-gridsasopts" ]]
then
GRIDSASOPTS="$GRIDSASOPTS $argument"
fi
ARGVAL_NEXT=""
elif [[ "$argument" == "-b" ]]
then
BATCH="YES"
elif [[ "$argument" == "-gridwork" || "$argument" == "-gridjobopts" || "$argument" == "-gridsasopts" ]]
then
ARGVAL_NEXT="$argument"
else
# All other options on the command line are SAS options.
GRIDSASOPTS="$GRIDSASOPTS $argument"
fi
done
##
## Get the base and directory name of the SAS script.
##
SCRIPT_BASE=`basename $SASSCRIPT | cut -d'.' -f1`
SCRIPT_DIR=`dirname $SASSCRIPT`
if [[ $SCRIPT_DIR = . ]]
then
SASSCRIPT=$PWD/$SASSCRIPT
SCRIPT_DIR=$PWD
fi
##
## Specify SAS options
## 1) nodms, noterminal, errorabend, and fullstimer
## 2) User specified options from the command-line
## 3) Source $HOME/autoexec.sas
##
GRIDSASOPTS="-nodms -noterminal -errorabend -fullstimer $GRIDSASOPTS"
if [[ -f $HOME/autoexec.sas ]]
then
GRIDSASOPTS="-autoexec $HOME/autoexec.sas $GRIDSASOPTS"
fi
if ((`expr "$GRIDSASOPTS" : ".*-log "` > 0))
then
##
## User specified -log option.
##
SASLOG=`echo $GRIDSASOPTS | sed "s/^.*-log//" | awk '{print $1}'`
##
## If the log file name doesn't include a directory, then prepend the
## current working directory to the log file name. Recreate GRIDSASOPTS
## with the full log file name and path.
##
LOGBASE=`basename $SASLOG | cut -d'.' -f1`
LOGDIR=`dirname $SASLOG`
if [[ $LOGDIR = . ]]
then
SASLOG_ORIG=$SASLOG
SASLOG=$PWD/$SASLOG
GRIDSASOPTS=`echo $GRIDSASOPTS | sed "s#-log $SASLOG_ORIG#-log $SASLOG#g"`
fi
if ((`expr "$GRIDSASOPTS" : ".*-print "` > 0))
then
##
## User specified -print option.
##
SASLST=`echo $GRIDSASOPTS | sed "s/^.*-print//" | awk '{print $1}'`
##
## If the lst file name doesn't include a directory, then prepend the
## current working directory to the lst file name. Recreate GRIDSASOPTS
## with the full lst file name and path.
##
LSTBASE=`basename $SASLST | cut -d'.' -f1`
LSTDIR=`dirname $SASLST`
if [[ $LSTDIR = . ]]
then
SASLST_ORIG=$SASLST
SASLST=$PWD/$SASLST
GRIDSASOPTS=`echo $GRIDSASOPTS | sed "s#-print $SASLST_ORIG#-print $SASLST#g"`
fi
else
##
## User specified -log without -print. Add -print option so that the
## log/lst are interleaved into one file.
##
GRIDSASOPTS="$GRIDSASOPTS -print $SASLOG"
fi
else
##
## User did not specify "-log" on the command line. Add that option
## and create the combined log/lst file in the same location as the script.
##
SASLOG=$SCRIPT_DIR/$SCRIPT_BASE.log
GRIDSASOPTS="$GRIDSASOPTS -log $SASLOG -print $SASLOG"
fi
##
## Remove SAS log and list if they already exist.
##
rm -f $SASLOG $SASLST
##
## Change -log and -print options to -altlog and -altprint.
##
GRIDSASOPTS=`echo $GRIDSASOPTS | sed 's/\-log/\-altlog/;s/\-print/\-altprint/'`
##
## Invoke the SAS script on the grid.
##
TMPFILE=`mktemp --suffix .out`
date "+%Y%m%d:%H%M%S: $SASSCRIPT starting"
date "+%Y%m%d:%H%M%S: GRIDSASOPTS=$GRIDSASOPTS"
if [[ "$GRIDWORK" != "" && "$GRIDJOBOPTS" != "" ]]
then
date "+%Y%m%d:%H%M%S: GRIDWORK=$GRIDWORK"
date "+%Y%m%d:%H%M%S: GRIDJOBOPTS=$GRIDJOBOPTS"
sasgsub -gridsubmitpgm $SASSCRIPT -gridwait -gridsasopts "'$GRIDSASOPTS'" \
-gridwork "'$GRIDWORK'" \
-gridjobopts "'$GRIDJOBOPTS'" | tee $TMPFILE
elif [[ "$GRIDWORK" != "" ]]
then
date "+%Y%m%d:%H%M%S: GRIDWORK=$GRIDWORK"
sasgsub -gridsubmitpgm $SASSCRIPT -gridwait -gridsasopts "'$GRIDSASOPTS'" \
-gridwork "'$GRIDWORK'" | tee $TMPFILE
elif [[ "$GRIDJOBOPTS" != "" ]]
then
date "+%Y%m%d:%H%M%S: GRIDJOBOPTS=$GRIDJOBOPTS"
sasgsub -gridsubmitpgm $SASSCRIPT -gridwait -gridsasopts "'$GRIDSASOPTS'" \
-gridjobopts "'$GRIDJOBOPTS'" | tee $TMPFILE
else
sasgsub -gridsubmitpgm $SASSCRIPT -gridwait -gridsasopts "'$GRIDSASOPTS'" \
| tee $TMPFILE
fi
##
## Sleep up to 120 seconds to give the NFS time so that the log file will
## appear.
##
I=0
while ((I<24))
do
if [[ -f $SASLOG ]]
then
break
fi
sleep 5
date "+%Y%m%d:%H%M%S: Waiting for $SASLOG; sleeping 5 seconds"
((I=I+1))
done
SASJOBID=`grep "^Job ID:" $TMPFILE | awk '{print $3}'`
rm -f $TMPFILE
##
## If there is no log file, then the SAS script was not executed. Show the
## history for the job and exit.
##
if [[ ! -f $SASLOG ]]
then
if [[ -n "$SASJOBID" ]]
then
bhist -l $SASJOBID
fi
date "+%Y%m%d:%H%M%S: $SASSCRIPT failed to execute; log file was not created"
exit 2
fi
##
## Check the log file for errors. Return non-0 if any errors occurred other
## than those in the OKAY_LIST.
##
OKAY_LIST="Cannot open X display"
OKAY_LIST="$OKAY_LIST|Errors printed on page"
NUM_ERRORS=$(grep '^ERROR:' $SASLOG | grep -vE "$OKAY_LIST" | wc -l)
if ((NUM_ERRORS > 0))
then
SASRC=3
else
SASRC=0
fi
if [[ "$BATCH" == "YES" ]]
then
cat $SASLOG
rm -f $SASLOG
fi
date "+%Y%m%d:%H%M%S: $SASSCRIPT exited with return code $SASRC"
exit $SASRC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment