#!/bin/sh # # Copyright 2007 SAS Institute Inc. # SAS Campus Drive, Cary, North Carolina 27513, USA. # All rights reserved. # #set -v #echo "running sas.servers" # # Sample boot-time script for SAS 9.1.3 SP4 BI Servers # Version V0.1 for RHEL 4 # # This script assumes that all listed SAS servers will be run on this # same platform. We do not check for, nor start SAS servers on remote # platforms. # # The SAS Metadata Server must start successfully before attempts are # made to start the other dependent servers. # # The script is intended to run at boot level 3 or 5. # # Put a copy of this script in /etc/init.d and set permissions to 0744, # owner=root. Add a hard link in /etc/rc3.d or rc5.d to this script from: # S99sas.servers # and a hard link in /etc/rc0.d to this script from: # K99sas.servers # # The "99" insures that the SAS Servers script is one of the last to # execute at boot, allowing NFS, etc. to start up first. The "S" link # be executed at startup and the "K" link will be executed at shutdown. # Runlevel 5 is network and gui. Runlevel 3 is network and command line. # #***** # # The following sets of variables will be automatically set by the # installer in 9.2+ installs. They must be set by hand at present. # #***** #***** # Each variable should be set to "yes" if that server type is installed, # or nothing if the particular server is not installed, for example: # # HAS_OLAP_SERVER= # #***** HAS_METADATA_SERVER=yes HAS_OLAP_SERVER= HAS_OBJECT_SPAWNER=yes HAS_SHARE_SERVER= HAS_CONNECT_SERVER= #***** # To avoid protection issues with installs mounted over NFS, this # script has to run under the same UID as that which owns the installed # SAS code. Define that UID here. #***** SASUID="sastux" #***** # # Configuration-dependent (pick one to uncomment) # #***** #Logmsg=Debug_Logmsg #Logmsg=Mandriva_Logmsg Logmsg=RHEL_Logmsg #Logmsg=SUSE_Logmsg #Logmsg=AIX_Logmsg #Logmsg=H6I_Logmsg #Logmsg=SOL9_Logmsg #Logmsg=SOL10_Logmsg #Logmsg=HPUX_Logmsg #***** # Uncomment for Solaris, #***** #WHOAMI="/usr/ucb/whoami" #TAIL="/usr/xpg4/bin/tail -n " # syntax different from deprecated /usr/bin/tail #***** # Uncomment for others #***** WHOAMI="/usr/bin/whoami" TAIL="/usr/bin/tail -n " #***** # # Where the SAS Metadata Server files live - this is installation-dependent. # Set the appropriate install directory for your configuration. The # double-quotes are important. # #***** METADATA_SERVER_DIR="/usr/local/SAS/Config/Lev1/SASMain/MetadataServer" METADATA_SERVER_LOGS="$METADATA_SERVER_DIR/logs" #***** # # Where other SAS servers live - these are installation-dependent. # Set the appropriate install directories for your configuration. # #***** OLAP_SERVER_DIR="/usr/local/SAS/Config/Lev1/SASMain/OLAPServer" OLAP_SERVER_LOGS="$OLAP_SERVER_DIR/logs" CONNECT_SERVER_DIR="/usr/local/SAS/Config/Lev1/SASMain/ConnectServer" CONNECT_SERVER_LOGS="$CONNECT_SERVER_DIR/logs" SHARE_SERVER_DIR="/usr/local/SAS/Config/Lev1/SASMain/ShareServer" SHARE_SERVER_LOGS="$SHARE_SERVER_DIR/logs" OBJECT_SPAWNER_DIR="/usr/local/SAS/Config/Lev1/SASMain/ObjectSpawner" OBJECT_SPAWNER_LOGS="$OBJECT_SPAWNER_DIR/logs" #***** # The following variable sets the number of, and delay between attempts # to start each SAS server. Each number is the sleep seconds to delay # before the next try. You probably don't need to change these. #***** RETRY_SERIES="2 2 2 5 5 5 5 5 5 5 5" #***** # # That is all that you should need to manually configure. # #***** #***** # # Don't change anything beyond here. # #***** # # The last thing that the server does when it comes up is log a listener # connection. Check for that string. # METADATA_SERVER_UP="Defined server listen connection" OLAP_SERVER_UP="Defined server listen connection" OBJECT_SPAWNER_UP="Objspawn has completed initialization" # # Subroutines/Functions # # # Check server status. We could invoke each server script with "status", # but it's quicker to do this directly. Note that if the status check # paradigm changes in the server scripts, those changes will need to # be propagated to here. # # This uses the cheap-but-quick approach that simply checks for # alive server PIDs. # server_status() { if [ -n "$HAS_METADATA_SERVER" ]; then { if [ -f $METADATA_SERVER_DIR/server.pid ]; then { pid=`cat $METADATA_SERVER_DIR/server.pid` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then $Logmsg "SAS Metadata Server (pid $pid) is running..." fi } else $Logmsg "SAS Metadata Server is stopped" fi } fi if [ -n "$HAS_OLAP_SERVER" ]; then { if [ -f $OLAP_SERVER_DIR/server.pid ]; then { pid=`cat $OLAP_SERVER_DIR/server.pid` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then $Logmsg "SAS OLAP Server (pid $pid) is running..." fi } else $Logmsg "SAS OLAP Server is stopped" fi } fi if [ -n "$HAS_OBJECT_SPAWNER" ]; then { if [ -f $OBJECT_SPAWNER_DIR/server.pid ]; then { pid=`cat $OBJECT_SPAWNER_DIR/server.pid` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then $Logmsg "SAS Object Spawner (pid $pid) is running..." fi } else $Logmsg "SAS Object Spawner is stopped" fi } fi if [ -n "$HAS_SHARE_SERVER" ]; then { if [ -f $SHARE_SERVER_DIR/server.pid ]; then { pid=`cat $SHARE_SERVER_DIR/server.pid` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then $Logmsg "SAS Share Server (pid $pid) is running..." fi } else $Logmsg "SAS Share Server is stopped" fi } fi if [ -n "$HAS_CONNECT_SERVER" ]; then { if [ -f $CONNECT_SERVER_DIR/server.pid ]; then { pid=`cat $CONNECT_SERVER_DIR/server.pid` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then $Logmsg "SAS Connect Server (pid $pid) is running..." fi } else $Logmsg "SAS Connect Server is stopped" fi } fi } is_server_up() { # # SAS servers typically write log information into a server-related # subdirectory, using logfile names that have the date encoded in them, # and rotate to a new logfile each day. The name format is typically of # the form: # # SomeServer_YYYY.MM.DD.log # # # A few servers still use a fixed name, e.g. "objspawn.log" # # Returns 1 if server is up, 0 if failure # ###### # Take as inputs the environment variables: # # LOGNAME prefix name of the server logfile, e.g. "MetadataServer" # LOGDIR directory where the logfiles are found # SERVER_UP log message that indicates that the server is alive # # The quick-and-dirty way to see if the server is up is to issue a # "kill -0 pid" against it. The following is a bit more robust in that # it checks the server log file to see if the server made it all the # way to the "listening for connections" stage. # # # Generate a log file name given today's date. # #echo generate log #echo scripttime $SCRIPT_TIME #echo logname $LOGNAME CHKLOG="`echo $LOGNAME $SCRIPT_TIME | awk '{ printf "%s_%s.%s.%s.log", $1, substr($2,1,4),substr($2,5,2),substr($2,7,2) }'`" #echo "logfile name is" $CHKLOG # # # Let the server come up to speed, then retry checking the log # a few times before deciding the server didn't make it up. # The numbers in RETRY_SERIES are sleep times (in seconds) before retry. # MATCH= for st in $RETRY_SERIES do sleep $st #echo do grep grep "$SERVER_UP" "$LOGDIR/$CHKLOG" > /dev/null 2>&1 if [ "$?" -eq 0 ]; then { #echo #echo #echo grep match #echo SERVER_UP is "$SERVER_UP" #echo LOG is "$LOGDIR/$CHKLOG" # # In some instances the last log line isn't terminated with # a newline. Some OS tail commands will combine this with the last line that # did have a newline, for example if you execute # cat foo | tail -n 1 # # To fix this, there is an embedded awk in the pipe to add newlines # MATCH=`grep "$SERVER_UP" "$LOGDIR/$CHKLOG" | awk '{ printf "%s\n", $0 }' | ${TAIL}1`; #echo checking $MATCH check_match; if [ "$?" -eq 1 ]; then return 1; # found a matching entry and it's newer than this run fi } fi done # # Last chance, the day may have rolled over while this script was running. # Check one more time using the new day's log file (if any). # new_day_match; if [ "$?" -eq 1 ]; then return 1; # got a valid match else return 0; fi } is_server_up_nostamp() { # # SAS servers typically write log information into a server-related # subdirectory, using logfile names that have the date encoded in them, # and rotate to a new logfile each day. # # A few servers still use a fixed name, e.g. "objspawn_console.log", so # we have a special-case routine to check if they're up. Note that not # only does the log name not get timestamped, but the log entries don't # either. Just check to see if the desired string is present in whatever # current logfile exists. If we find the string, see if the associated # server PID file results in an active PID. # # Returns 1 if server is up, 0 if failure # ###### # Take as inputs the environment variables: # # LOGNAME prefix name of the server logfile, e.g. "MetadataServer" # LOGDIR directory where the logfiles are found # SERVER_UP log message that indicates that the server is alive # SERVER_PID_FILE file where the server's PID is stored at startup # CHKLOG="$LOGNAME.log" #echo "logfile name is" $CHKLOG # # # Let the server come up to speed, then retry checking the log # a few times before deciding the server didn't make it up. # The numbers n RETRY_SERIES are sleep times (in seconds) before retry. # MATCH= for st in $RETRY_SERIES do sleep $st #echo do grep grep "$SERVER_UP" "$LOGDIR/$CHKLOG" > /dev/null 2>&1 if [ "$?" -eq 0 ]; then { #echo #echo #echo grep match if [ -f $SERVER_PID_FILE ]; # got a PID file? then { pid=`cat $SERVER_PID_FILE` kill -0 $pid >/dev/null 2>&1 if [ $? -eq 0 ]; then return 1; # PID is active else return 0; # PID not active fi } else # can't access PID file continue; # try again fi } fi done # # Fell out of the loop; assume that either the logfile doesn't exist # or the desired string wasn't there. In either case, the server must # not be up. return 0; } check_match () { # # If MATCH is non-null, we found the target string in the log file. # Now make sure that it was logged *after* we started this script (there # could be pre-existing successful starts since the logs get appended to). # # Passed in environment: # $LOGNAME is the server log name prefix # $LOGDIR is the directory where the log files are found. # $MATCH contains the line found in the logfile via grep. # $SCRIPT_TIME contains the date string from when this script was invoked. # # Returns 0 on failure (too old), 1 on success # MATCHDATE="`echo $MATCH | awk '{ printf "%s%s%s%s",substr($1,1,8),substr($1,10,2),substr($1,13,2),substr($1,16,2) }'`" SCRIPTDATE="`echo $SCRIPT_TIME | awk '{ printf "%s%s%s%s",substr($1,1,8),substr($1,9,2),substr($1,11,2),substr($1,13,2) }'`" #echo Match is "$MATCHDATE" #echo ScriptDate is "$SCRIPTDATE" #echo ScriptTime is "$SCRIPT_TIME" if [ $SCRIPTDATE -lt $MATCHDATE ]; then return 1; # Good match else return 0; # Bad match fi } new_day_match () { # # There is a very slight possibility that the date # rolled over between the time that the boot script started and the # time that the server created the log file. See if the day changed. # If so, reset the logfile pointer and check one final time. # # Passed in environment: # $LOGNAME is the server log name prefix # $LOGDIR is the directory where the log files are found. # $SERVER_UP is the pattern used by grep to search the log file. # $SCRIPT_TIME contains the date string from wheh this script was invoked. # # Returns 0 on match failure, 1 on success # CURDAY=`date +%d` SCRIPT_DAY="`echo $SCRIPT_TIME | awk '{ printf substr($1,7,2) }'`" if [ "$SCRIPT_DAY" != "$CURDAY" ]; # day must have rolled over then { CHKLOG="`echo $LOGNAME $SCRIPT_TIME $CURDAY | awk '{ printf "%s_%s.%s.%s.log",$1,substr($2,1,4),substr($2,5,2),$3 }'`" #echo Curday CHKLOG is "$CHKLOG" if [ -r "$LOGDIR/$CHKLOG" ]; # does a new log file exist? then { MATCH=`grep "$SERVER_UP" "$LOGDIR/$CHKLOG"`; # # Find any "server up" indication? # if [ -z "$MATCH" ]; then return 0; # No. else return 1; # Yes, by definition, this instance is newer than fi # the boot script run time, so server is up. } else return 0; # No such log file fi } fi return 0; # Day didn't roll over } start_metadata_server() { # # Start SAS Metadata Server # #echo Start metadata if [ -x $METADATA_SERVER_DIR/MetadataServer.sh ]; then { #echo do metadata script $METADATA_SERVER_DIR/MetadataServer.sh start >/dev/null 2>&1 if [ "$?" -ne 0 ]; then return 1; fi #echo do logname LOGNAME="MetadataServer" LOGDIR="$METADATA_SERVER_LOGS" SERVER_UP="$METADATA_SERVER_UP" #echo calling is_up is_server_up; if [ "$?" -eq 1 ]; then return 0; # Yes else return 1; # No fi } fi return 1; } start_olap_server() { if [ -x $OLAP_SERVER_DIR/OLAPServer.sh ]; then { $OLAP_SERVER_DIR/OLAPServer.sh start >/dev/null 2>&1 if [ "$?" -ne 0 ]; then return 1; fi LOGNAME="OLAPServer" LOGDIR="$OLAP_SERVER_LOGS" SERVER_UP="$OLAP_SERVER_UP" is_server_up; if [ "$?" -eq 1 ]; then return 0; # Yes else return 1; # No fi } fi return 1; } start_object_spawner() { if [ -x $OBJECT_SPAWNER_DIR/ObjectSpawner.sh ]; then { $OBJECT_SPAWNER_DIR/ObjectSpawner.sh start >/dev/null 2>&1 if [ "$?" -ne 0 ]; then return 1; fi LOGNAME="objspawn_console" LOGDIR="$OBJECT_SPAWNER_LOGS" SERVER_UP="$OBJECT_SPAWNER_UP" SERVER_PID_FILE="$OBJECT_SPAWNER_DIR/server.pid" # # ObjectSpawner is a special case: it doesn't timestamp entries in # its logfile. The best we can do at present is check for an "alive" # message, then check for an active PID associated with the task. # is_server_up_nostamp; if [ "$?" -eq 1 ]; then return 0; # Yes else return 1; # No fi } fi return 1; # can't execute the server script } start_share_server() { if [ -x $SHARE_SERVER_DIR/ShareServer.sh ]; then { $SHARE_SERVER_DIR/ShareServer.sh start >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } start_connect_server() { if [ -x $CONNECT_SERVER_DIR/ConnectServer.sh ]; then { $CONNECT_SERVER_DIR/ConnectServer.sh start >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } stop_metadata_server() { if [ -x $METADATA_SERVER_DIR/MetadataServer.sh ]; then { $METADATA_SERVER_DIR/MetadataServer.sh stop >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } stop_olap_server() { if [ -x $OLAP_SERVER_DIR/OLAPServer.sh ]; then { $OLAP_SERVER_DIR/OLAPServer.sh stop >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } stop_object_spawner() { if [ -x $OBJECT_SPAWNER_DIR/ObjectSpawner.sh ]; then { $OBJECT_SPAWNER_DIR/ObjectSpawner.sh stop >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } stop_share_server() { if [ -x $SHARE_SERVER_DIR/ShareServer.sh ]; then { $SHARE_SERVER_DIR/ShareServer.sh stop >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } stop_connect_server() { if [ -x $CONNECT_SERVER_DIR/ConnectServer.sh ]; then { $CONNECT_SERVER_DIR/ConnectServer.sh stop >/dev/null 2>&1 rc=$?; return $rc; } fi return 1; } Debug_Logmsg() { echo "$*" } Mandriva_Logmsg() { echo "$*" } RHEL_Logmsg() { echo "$*" } SUSE_Logmsg() { echo "$*" } AIX_Logmsg() { echo "$*" } H6I_Logmsg() { echo "$*" } SOL9_Logmsg() { echo "$*" } SOL10_Logmsg() { echo "$*" } HPUX_Logmsg() { echo "$*" } start_servers () { # # We use the current time to figure out which log file to check # # This could break if the system is rebooted right at midnight, since the date # may wrap. We'll check for that if the initial log file existence fails. # SCRIPT_TIME=`date +%Y%m%d%H%M%S` # # Crank everything up # $Logmsg "Starting SAS servers" # # SAS Metadata server has to precede the others. # #echo has_meta $HAS_METADATASERVER if [ -z "$HAS_METADATA_SERVER" ]; then { # # if no MetadataServer is installed, nothing else should be started. # $Logmsg "SAS Metadata Server is NOT installed." $Logmsg "The following SAS servers will NOT be started as a result:" SRVLIST=" " if [ -n "$HAS_OLAP_SERVER" ]; then SRVLIST="$SRVLIST OLAP"; fi if [ -n "$HAS_OBJECT_SPAWNER" ]; then SRVLIST="$SRVLIST OBJECT_SPAWNER"; fi if [ -n "$HAS_SHARE_SERVER" ]; then SRVLIST="$SRVLIST SHARE_SERVER"; fi if [ -n "$HAS_CONNECT_SERVER" ]; then SRVLIST="$SRVLIST CONNECT_SERVER"; fi $Logmsg "$SRVLIST"; return 1; } else { start_metadata_server; #echo back from start meta if [ "$?" -eq 0 ]; then { $Logmsg "SAS Metadata Server is UP"; } else { $Logmsg "SAS Metadata Server is NOT up"; $Logmsg "The following SAS servers will NOT be started as a result:" SRVLIST=" " if [ -n "$HAS_OLAP_SERVER" ]; then SRVLIST="$SRVLIST OLAP"; fi if [ -n "$HAS_OBJECT_SPAWNER" ]; then SRVLIST="$SRVLIST OBJECT_SPAWNER"; fi if [ -n "$HAS_SHARE_SERVER" ]; then SRVLIST="$SRVLIST SHARE_SERVER"; fi if [ -n "$HAS_CONNECT_SERVER" ]; then SRVLIST="$SRVLIST CONNECT_SERVER"; fi $Logmsg "$SRVLIST"; return 1; } fi } fi # # If we got here, Metadata is up, so try to start the additonal servers. # Note that even if one of these fails to start, the process will continue # starting the others. Success/Failure is sent to the log. # if [ -n "$HAS_OLAP_SERVER" ] then { start_olap_server; if [ "$?" -eq 0 ]; then $Logmsg "SAS OLAP Server is UP"; else $Logmsg "SAS OLAP Server is NOT up"; fi; } fi if [ -n "$HAS_OBJECT_SPAWNER" ] then { start_object_spawner; if [ "$?" -eq 0 ]; then $Logmsg "SAS Object Spawner is UP"; else $Logmsg "SAS Object Spawner is NOT up"; fi; } fi if [ -n "$HAS_SHARE_SERVER" ] then { start_share_server; if [ "$?" -eq 0 ]; then $Logmsg "SAS Share Server is UP"; else $Logmsg "SAS Share Server is NOT up"; fi; } fi if [ -n "$HAS_CONNECT_SERVER" ] then { start_connect_server; if [ "$?" -eq 0 ]; then $Logmsg "SAS Connect Server is UP"; else $Logmsg "SAS Connect Server is NOT up"; fi; } fi } stop_servers () { # # Shut everything down # We assume that the assorted "stop" scripts will succeed. # $Logmsg "Stopping SAS servers" if [ -n "$HAS_OLAP_SERVER" ] then stop_olap_server; fi; if [ -n "$HAS_OBJECT_SPAWNER" ] then stop_object_spawner; fi; if [ -n "$HAS_SHARE_SERVER" ] then stop_share_server; fi; if [ -n "$HAS_CONNECT_SERVER" ] then stop_connect_server; fi; # # stop Metadata last since some of the other servers depend on it. # if [ -n "$HAS_METADATA_SERVER" ]; then stop_metadata_server; fi; } # # Main processing routine # # To avoid protection issues for installs mounted over NFS, rerun # ourselves as the UID that owns the installed SAS code. # #echo UID is `$WHOAMI` if [ `$WHOAMI` != "$SASUID" ]; then { #echo Invoking su $SASUID -c $0 $1 su "$SASUID" -c "$0 $1" exit $? } fi case "$1" in start) start_servers; exit $? ;; stop) stop_servers; ;; restart|reload) stop_servers; start_servers; exit $? ;; status) server_status; exit $? ;; *) $Logmsg "$0: Unknown option" exit 1; esac