#!/bin/bash
##############################################################################
#
# Init script for Nginx webservers. Located in /sites/utils/local/bin.
#
##############################################################################
#Setup our base
BASEDIR=${BASEDIR:="/sites/utils/local"}
# Source the appctl-base file for common functions and ENV variables
[ -f $BASEDIR/lib/appctl-base ] && . $BASEDIR/lib/appctl-base
ULIMIT_MAX_FILES="$ULIMIT -S -n $($ULIMIT -H -n)"
# Set the maximum number of file descriptors allowed per child process.
if [ "x$ULIMIT_MAX_FILES" != "x" ]; then
$ULIMIT_MAX_FILES
fi
INSTANCE=$1
COMMAND=$2
F5TOOL=$F5MEMBERSTATUS
CMDPREFIX=""
# Base webserver directory
WWW_BASE=/sites/www-site
# Directory for Pre/Post Event Hook scripts
HOOKS_DIR="$WWW_BASE/hooks"
OS_TYPE=$($UNAME)
if [ "$OS_TYPE" = 'SunOS' ]; then
LD_LIBRARY_PATH=/usr/openwin/lib:/opt/sfw/lib:/usr/lib:/usr/local/lib:/usr/ccs/lib:/usr/4lib:$LD_LIBRARY_PATH:/$BASEDIR/lib:/sites/www-site/APACHE/lib
else # Linux
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/$BASEDIR/lib:/sites/www-site/APACHE/lib
fi
export LD_LIBRARY_PATH
# Use values from global_environment if they're defined. Otherwise use these defaults.
NGINX=${NGINX:-"/sites/utils/bin/nginx"}
CTLFILE=${CTL_INPUT_BOTHELLWEBS:-"/sites/utils/local/etc/ctl/ctl.input-bothellwebs"}
# Redefined in main
DATACENTER=''
#No trailing slash on CONFBASE, its added on by CONFDIR.
CONFBASE=${CONFBASE:-"/sites/www-site/conf"}
CONFDIR=${CONFDIR:-"$CONFBASE/$($ECHO $INSTANCE | $CUT -d - -f 1)"}
CFGFILE=${CFGFILE:-"${CONFDIR}/nginx-${INSTANCE}.conf"}
LOGDIR=${LOGDIR:-"/sites/www-site/logs"}
SSLDOMAINFILE=${SSLDOMAINFILE:-"/sites/utils/local/etc/ctl/webinstance-domain.conf"}
CHIPSETFILE=${CHIPSETFILE:-"/sites/utils/local/etc/ctl/webserver-chipset.conf"}
CERTSDIR=${CERTSDIR:-"/sites/www-site/prod_ssl_certs"}
OPENSSL=${OPENSSL:-"/sites/www-site/OPENSSL/openssl-1.0.0g-niagara2-64"}
#header vars
CLUSTER=$($GETCTLATTRIBUTE $CTLFILE ${HOSTNAME} $INSTANCE cluster)
#Source the override files, ultimately used to run different
# NGINX binaries and openssl libraries per-instance if necessary.
#instance-level override, synched
[ "$OS_TYPE" = 'SunOS' ] && [ -f $CONFDIR/webctl-override.cfg ] && readAndSourceFile $CONFDIR/webctl-override.cfg
#instance-level override, not synched.
[ -f /sites/www-site/$INSTANCE-override.cfg ] && readAndSourceFile /sites/www-site/$INSTANCE-override.cfg
# Number of days to keep log files if rotating
NUMDAYS=90
#Capture the A10 control passwords
A10USER=`$GETCREDENTIALS -i 201 -u 2>/dev/null`
A10PASS=`$GETCREDENTIALS -i 201 -p -d 2>/dev/null`
##
# Usage
###
usage() {
$ECHO "Usage: $0 instancename <status|start|stop|reload|restart|kill|startsessions|stopsessions|killsessions|clearcache|flushlogs|rotatelogs>"
return 1
}
##
# Escape quotes in a string
##
escapeQuotes() {
$ECHO $1 | sed 's/"/\\"/g'
}
##
# Get PIDS
###
getPids() {
BASECFGFILE=$($BASENAME $CFGFILE)
CMD="$PS auxwww | $EGREP \"^ *(www|root).*nginx.*$BASECFGFILE\" | $GREP -v grep"
if [ "$ME" = "atg" ]
then
CMD="$CMDPREFIX \"$(escapeQuotes "$CMD")\""
fi
eval $CMD | awk '{print $2}'
}
setupEnv() {
ROOTDIR=`dirname $NGINX`
ROOTDIR="$ROOTDIR/../"
NGINX_CMD="X_CLUSTER=$CLUSTER X_INSTANCE=$INSTANCE X_HOST=${HOSTNAME} $NGINX -p ${WWW_BASE} -c $CFGFILE"
}
##
# Start or Stop
###
startOrStopCmd() {
command=$1
rval=""
setupEnv
if [ "$command" = "start" ]; then
# Clear log symlinks
$CMDPREFIX "$FIND ${LOGDIR}/ -maxdepth 1 -type l -regex \".*[-_]${INSTANCE}\.log\" -delete"
#Echo the startup logs into what would be the error log
#TODO: Disabled as this script doesn't have perms to write to that file.
#echoReadFiles >> $LOGDIR/error_${INSTANCE}.log
# Pass the SSL cert value on the command line.
# If no value was defined then SSLSTRING is empty.
$CMDPREFIX "${NGINX_CMD}"
if [ $? -eq 0 ]; then
$ECHO "NGINX started."
rval=0
else
$ECHO "NGINX failed to start."
rval=1
fi
elif [ "$command" = "stop" ]; then
MESSAGE=
RVAL=
$CMDPREFIX "${NGINX_CMD} -s stop"
if [ $? -eq 0 ]; then
[ -z "$MESSAGE" ] && export MESSAGE="NGINX is being stopped."
[ -z "$RVAL" ] && export RVAL=0
else
export MESSAGE="NGINX failed to stop."
export RVAL=1
fi
$ECHO $MESSAGE
fi
return $RVAL
}
##
# Kill Command
###
killCmd() {
stat="x"
for pass in 1 2; do
pids=$(getPids)
if [ "$pass" -eq 1 -a -z "$pids" ]; then
stat="x0"
break
else
for p in $pids; do
$ECHO "killing process $p..."
if [ "$ME" = "atg" ]; then
sudo su - www -c "$KILL -KILL $p"
else
$KILL -KILL $p
fi
done
fi
# Sleep and do another kill because first try doesn't always work.
$SLEEP 5
done
if [ "$stat" = "x" ]; then
return 0
else
$ECHO "No processes to kill."
return 1
fi
}
##
# Output status of instance for F5 and Apache
###
fullStatus() {
[ $# -ne 1 ] && $ECHO 1>&2 "Incorrect # of fullStatus arguments" && exit 1
INSTANCE_NAME=$1
F5STATUS=$(f5Status $INSTANCE_NAME)
F5RETCODE=$?
APACHESTATUS=$(getStatus)
ARETCODE=$?
$ECHO "$F5STATUS $APACHESTATUS"
[ $F5RETCODE -ne 0 ] && return 1
return $ARETCODE
}
##
# Get Status
###
getStatus() {
pids=$(getPids)
if [ -n "$pids" ]; then
$ECHO "NGINX is running."
return 0
else
$ECHO "NGINX is not running."
return 1
fi
}
##
# Get server chipset,used to choose which apache subversion to run
##
getChipset() {
[ ! -e $CHIPSETFILE ] && $ECHO 1>&2 "Could not find chipset file" && return
ARCH=$($PRTCONF | $HEAD -5 | $TAIL -1 | $CUT -d, -f2)
[ -z "$ARCH" ] && $ECHO 1>&2 "Could not find architecture" && return
CHIPSET=$($GREP -w "$ARCH" $CHIPSETFILE | $CUT -d, -f2 | $HEAD -1)
[ -z "$CHIPSET" ] && $ECHO 1>&2 "Could not find $ARCH in $CHIPSETFILE" && return
$ECHO "$CHIPSET"
}
##
# Get chipspecific version
# Take a path and attempt to find a processor specific version of it.
# such as OPENSSL, or httpd. If the specified location cannot be found then blows up.
# Accepts the @CHIPSET@ macro
##
getChipsetSpecificPath() {
[ $# -ne 1 ] && $ECHO 1>&2 "Incorrect # of getChipsetSpecificPath arguments" && exit 1
#If no chipset is found, default to niagara
# If no target is found with that chipset, try blank
TARGET=$1
CHIPSET=`getChipset`
for x in -$CHIPSET -niagara ''; do
TMPTARGET=$TARGET
TMPTARGET=${TMPTARGET//@CHIPSET@/$x}
[ -e $TMPTARGET ] && $ECHO $TMPTARGET && return
done
#If we are here then nothing matched
$ECHO 1>&2 "Could not find matching target for $TARGET" && exit 1
}
##
# Stop Sessions
# F5s do stopsessions via SOAP. A10s do it via changing the healthcheck file.
###
stopSessions() {
[ $# -ne 1 ] && $ECHO 1>&2 "Incorrect # of stopSessions arguments" && exit 1
INSTANCE_NAME=$1
ADDRESS=$(getAddress)
callHelper $HOOKS_DIR/$PRE_STOP_SESSIONS
$ECHO "Stopping sessions of $INSTANCE_NAME"
ERROR=0
pools=$(getF5Pools $INSTANCE_NAME)
touch /sites/utils/tmp/$INSTANCE_NAME.disable && $CHMOD 666 /sites/utils/tmp/$INSTANCE_NAME.disable
for POOLINFO in $pools; do
F5SERVER=$($ECHO $POOLINFO | $CUT -d\| -f 1)
F5POOL=$($ECHO $POOLINFO | $CUT -d\| -f 2)
#POOL example: pSTANDALONE_443,
PORT_STUB=$($ECHO $POOLINFO | $SED -e 's/_/ /g' | $AWK '{print $NF}')
# 443/ 80 for most, or 19443 for fulfillment
#fulfillment, vend pool names are their exact listening port.
if [ $PORT_STUB -gt 999 ]; then
PORT=$PORT_STUB
else
# Some virtual servers listen on high ports, so we check for
PORT=$(( $($ECHO $INSTANCE | $CUT -d"-" -f2) * 1000 + $PORT_STUB ))
fi
#Determine if this is a a10 or F5 call
expr "$F5POOL" : "ap" >/dev/null && IS10=1
if [ -n "$IS10" ]; then
#Enable the port, in case it was previously disabled
SESSIONID=`$WGET "https://$F5SERVER/services/rest/V1.1/?method=authenticate&username=${A10USER}&password=${A10PASS}" --no-check-certificate -O- -q | $CUT -d\< -f 4 | $CUT -d\> -f 2`
$WGET "https://$F5SERVER/services/rest/V1.1/?session_id=$SESSIONID&method=slb.server.update&address=$ADDRESS&port-list=port1&port1=port_num%03$PORT%02protocol%032%02status%031" --no-check-certificate -O- -q |xmllint --format -| $GREP -w ok >/dev/null 2>&1
RESULT=$?
$ECHO "$F5SERVER:$PORT state set to 'STATE_DISABLED/STATE_ENABLED"
if [ $RESULT -eq 0 ]; then
$ECHO "Suspend returned success for $F5SERVER|$F5POOL"
else
$ECHO "Suspend failed for $F5SERVER|$F5POOL"
fi
else
$F5TOOL $F5SERVER $F5POOL $ADDRESS:$PORT disable
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
$ECHO "ERROR: disable returned nonzero returncode for $POOLINFO"
let ERROR=ERROR+1
else
$ECHO "Suspend returned success for $POOLINFO"
fi
fi
done
callHelper $HOOKS_DIR/$POST_STOP_SESSIONS
return $ERROR
}
##
# Start Sessions
###
startSessions() {
[ $# -ne 1 ] && $ECHO 1>&2 "Incorrect # of startSessions arguments" && exit 1
INSTANCE_NAME=$1
ADDRESS=$(getAddress)
callHelper $HOOKS_DIR/$PRE_START_SESSIONS
$ECHO "Starting sessions of $INSTANCE_NAME"
ERROR=0
pools=$(getF5Pools $INSTANCE_NAME)
[[ -e /sites/utils/tmp/$INSTANCE_NAME.disable ]] && rm -f /sites/utils/tmp/$INSTANCE_NAME.disable
for POOLINFO in $pools; do
F5SERVER=$($ECHO $POOLINFO | $CUT -d\| -f 1)
F5POOL=$($ECHO $POOLINFO | $CUT -d\| -f 2)
#POOL example: pSTANDALONE_443,
PORT_STUB=$($ECHO $POOLINFO | $SED -e 's/_/ /g' | $AWK '{print $NF}')
# 443/ 80 for most, or 19443 for fulfillment
#fulfillment, vend pool names are their exact listening port.
if [ $PORT_STUB -gt 999 ]; then
PORT=$PORT_STUB
else
# Some virtual servers listen on high ports, so we check for
PORT=$(( $($ECHO $INSTANCE | $CUT -d"-" -f2) * 1000 + $PORT_STUB ))
fi
#Determine if this is a a10 or F5 call
expr "$F5POOL" : "ap" >/dev/null && IS10=1
if [ -n "$IS10" ]; then
SESSIONID=`$WGET "https://$F5SERVER/services/rest/V1.1/?method=authenticate&username=${A10USER}&password=${A10PASS}" --no-check-certificate -O- -q | cut -d\< -f 4 | cut -d\> -f 2`
$WGET "https://$F5SERVER/services/rest/V1.1/?session_id=$SESSIONID&method=slb.server.update&address=$ADDRESS&port-list=port1&port1=port_num%03$PORT%02protocol%032%02status%031" --no-check-certificate -O- -q |xmllint --format -| $GREP -w ok >/dev/null 2>&1
RESULT=$?
$ECHO "$F5SERVER:$PORT state set to 'STATE_ENABLED/STATE_ENABLED"
if [ $RESULT -eq 0 ]; then
$ECHO "Enable returned success for $F5SERVER|$F5POOL"
else
$ECHO "Enable failed for $F5SERVER|$F5POOL"
fi
else
$F5TOOL $F5SERVER $F5POOL $ADDRESS:$PORT enable
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
$ECHO "ERROR: enable returned nonzero returncode for $POOLINFO"
let ERROR=ERROR+1
else
$ECHO "Enable returned success for $POOLINFO"
fi
fi
done
callHelper $HOOKS_DIR/$POST_START_SESSIONS
return $ERROR
}
##
# Kill Sessions
###
killSessions() {
[ $# -ne 1 ] && $ECHO 1>&2 "Incorrect # of startSessions arguments" && exit 1
INSTANCE_NAME=$1
ADDRESS=$(getAddress)
callHelper $HOOKS_DIR/$PRE_KILL_SESSIONS
$ECHO "Killing sessions of $INSTANCE_NAME"
ERROR=0
touch /sites/utils/tmp/$INSTANCE_NAME.disable && $CHMOD 666 /sites/utils/tmp/$INSTANCE_NAME.disable
pools=$(getF5Pools $INSTANCE_NAME)
for POOLINFO in $pools; do
F5SERVER=$($ECHO $POOLINFO | $CUT -d\| -f 1)
F5POOL=$($ECHO $POOLINFO | $CUT -d\| -f 2)
#POOL example: pSTANDALONE_443,
PORT_STUB=$($ECHO $POOLINFO | $SED -e 's/_/ /g' | $AWK '{print $NF}')
# 443/ 80 for most, or 19443 for fulfillment
#fulfillment, vend pool names are their exact listening port.
if [ $PORT_STUB -gt 999 ]; then
PORT=$PORT_STUB
else
# Some virtual servers listen on high ports, so we check for
PORT=$(( $($ECHO $INSTANCE | $CUT -d"-" -f2) * 1000 + $PORT_STUB ))
fi
#Determine if this is a a10 or F5 call
expr "$F5POOL" : "ap" >/dev/null && IS10=1
if [ -n "$IS10" ]; then
#Remove the disable file and enable the port, in case it was previously disabled
SESSIONID=`$WGET "https://$F5SERVER/services/rest/V1.1/?method=authenticate&username=${A10USER}&password=${A10PASS}" --no-check-certificate -O- -q | cut -d\< -f 4 | cut -d\> -f 2`
$WGET "https://$F5SERVER/services/rest/V1.1/?session_id=$SESSIONID&method=slb.server.update&address=$ADDRESS&port-list=port1&port1=port_num%03$PORT%02protocol%032%02status%030" --no-check-certificate -O- -q |xmllint --format -| $GREP -w ok >/dev/null 2>&1
RESULT=$?
$ECHO "$F5SERVER:$PORT state set to 'STATE_DISABLED/STATE_DISABLED"
if [ $RESULT -eq 0 ]; then
$ECHO "Kill returned success for $F5SERVER|$F5POOL"
else
$ECHO "Kill failed for $F5SERVER|$F5POOL"
fi
else
$F5TOOL $F5SERVER $F5POOL $ADDRESS:$PORT kill
RETCODE=$?
if [ $RETCODE -ne 0 ]; then
$ECHO "ERROR: Kill returned nonzero returncode for $POOLINFO"
let ERROR=ERROR+1
else
$ECHO "Kill returned success for $POOLINFO"
fi
fi
done
callHelper $HOOKS_DIR/$POST_KILL_SESSIONS
return $ERROR
}
##
# Restart Monitor Scripts
###
restartMonitors() {
$WLTAILER stop
$SNMPSUBAGENT stop
$SLEEP 2
$PS -ef | $EGREP '(jmxgetbea|snmpsuba)'| $AWK '{print $2}' | $XARGS $KILL
$SLEEP 2
$WLTAILER start
$SLEEP 2
$SNMPSUBAGENT start
}
##
# Rotate Logs
###
rotateLogs() {
logs=$($LS $LOGDIR/*${INSTANCE}.log 2>/dev/null)
if [ -n "$logs" ]; then
local dt=$($DATE +%Y%m%d)
for log in $logs; do
log=$(basename $log)
$CMDPREFIX "$MV $LOGDIR/$log $LOGDIR/archives/$log-$dt"
if [ $? -ne 0 ]; then
echo "Could not move file $log to archives"
return 1
fi
$CMDPREFIX "$NICE $GZIP -f $LOGDIR/archives/$log-$dt </dev/null >/dev/null 2>/dev/null &"
done
else
$ECHO "No logs to rotate"
return 1
fi
# tell nginx to rotate logs
setupEnv
$CMDPREFIX "${NGINX_CMD} -s reopen"
}
##
# Flush Logs from memory
##
flushLogs() {
echo 'Flushing nginx logs.'
setupEnv
$CMDPREFIX "${NGINX_CMD} -s reopen"
}
##
# Reload nginx
##
reloadNginx() {
echo 'Reloading nginx process.'
setupEnv
$CMDPREFIX "${NGINX_CMD} -s reload"
}
clearCache() {
local envname="$($ECHO $INSTANCE | $CUT -d - -f 1)"
echo "Clearing cache by rm /tmp/.nginx_*_$INSTANCE /sites/utils/tmp/.nginx_*_$INSTANCE /tmp/.nginx_*_$envname /sites/utils/tmp/.nginx_*_$envname"
$CMDPREFIX "rm -rf /tmp/.nginx_*_$INSTANCE /sites/utils/tmp/.nginx_*_$INSTANCE /tmp/.nginx_*_$envname /sites/utils/tmp/.nginx_*_$envname"
reloadNginx
}
##
# Main
###
main() {
# Check that command line was complete
if [ ! -n "$INSTANCE" -o ! -n "$COMMAND" ]; then
usage
exit $?
fi
# Must be run as atg, www or root
if [ "$ME" != "root" -a "$ME" != "www" -a "$ME" != 'atg' ]; then
$ECHO "You must be root or the www or atg user to run this script."
exit 1
fi
# Check that required tools work
for x in CTLATTRIBUTETOOL WGET PS; do
eval value=\$$x
if [ ! -x "$value" ]; then
$ECHO "Unable to execute $x: $value, results indeterminate" >&2
exit 1
fi
done
# Check for F5 tool
if [ ! -f $F5TOOL ]; then
$ECHO "Not found F5TOOL: $F5TOOL , aborting." >&2
exit 1
fi
# Check for config file's existence
if [ ! -e $CFGFILE ]; then
$ECHO "$CFGFILE not found, aborting." >&2
exit 1
fi
###
# If we are on privileged port (< 1024) then run as root, otherwise we'll run as www in the command prefix.
# This will ignore lines that start with a # in the first column.
###
# get list of ports this instance listens on
LISTENPORTS=$($GREP -E '^[\t ]*Listen[\t ]+' $CFGFILE | $SED 's/^[ \t]*Listen[\t ]*//' | $SED 's/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*://')
# cycle through list and see if any are privileged
ROOT=0
LISTEN=0
for port in $LISTENPORTS
do
LISTEN=1
[ $port -lt 1024 ] && ROOT=1
done
if [ $LISTEN -eq 1 ]; then
if [ $ROOT -eq 1 ]; then
if [ "$ME" = "root" ]; then
CMDPREFIX="$SH -c"
else
$ECHO "Listen port is privileged and this script was not run as root. Aborting."
exit 1
fi
else
if [ "$ME" = "www" ]; then
CMDPREFIX="$SH -c"
elif [ "$ME" = 'root' ]; then
CMDPREFIX="$SU - www -c"
else
CMDPREFIX="$SUDO $SU - www -c"
fi
fi
else # for some reason we did not find a Listen port so default to using sudo
CMDPREFIX="$SUDO $SU - www -c"
fi
# Define DATACENTER and verify it is set.
DATACENTER=${DATACENTER:-$($CTLATTRIBUTETOOL $CTLFILE $HOSTNAME $INSTANCE datacenter)}
if [ -z "$DATACENTER" ]; then
$ECHO "No datacenter defined for this instance -- update the ctl input file. Aborting." >&2
exit 1
fi
# Get the chipset specific httpd,openssl
if [ "$OS_TYPE" = 'SunOS' ]; then
NGINX=`getChipsetSpecificPath $NGINX`
OPENSSL=`getChipsetSpecificPath $OPENSSL`
fi
LD_LIBRARY_PATH=$OPENSSL/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
# Process Command
case $COMMAND in
start|stop) startOrStopCmd $COMMAND; exit $?
;;
reload) reloadNginx; exit $?
;;
restart) startOrStopCmd stop; sleep 5; startOrStopCmd start; exit $?
;;
kill) killCmd; exit $?
;;
status) fullStatus $INSTANCE; exit $?
;;
f5status) f5Status $INSTANCE; exit $?
;;
restartmonitors) restartMonitors; exit $?
;;
startsessions) startSessions $INSTANCE; exit $?
;;
stopsessions) stopSessions $INSTANCE; exit $?
;;
killsessions) killSessions $INSTANCE; exit $?
;;
clearcache) clearCache; exit $?
;;
flushlog|flushlogs) flushLogs; exit $?
;;
rotatelog|rotatelogs) rotateLogs; exit $?
;;
help|*) usage; exit 1
;;
esac
}
## Main ##
main $@
No comments:
Post a Comment