Skip to content

Instantly share code, notes, and snippets.

@frbayart
Created October 5, 2015 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frbayart/4e1bf257690ba2298460 to your computer and use it in GitHub Desktop.
Save frbayart/4e1bf257690ba2298460 to your computer and use it in GitHub Desktop.
rudder-agent init script with PID check, loop to force stop
#!/bin/bash
#====================================================================
# Start/stop script for CFEngine Community
# (http://www.cfengine.com).
#
# chkconfig: 2345 85 15
# description: CFEngine Community
#
### BEGIN INIT INFO
# Provides: rudder-agent
# Required-Start: $remote_fs $syslog $all
# Required-Stop: $remote_fs $syslog
# Should-Start: $network $time
# Should-Stop: $network $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: CFEngine Community
# Description: CFEngine Community init script provided by Normation
### END INIT INFO
#
# Copyright (C) 2010 Normation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# GPL License: http://www.gnu.org/licenses/gpl.txt
#
#====================================================================
#====================================================================
# Changelog
#====================================================================
# Version 0.1 (12/2010):
# - First version
# Author: Jonathan Clarke <jonathan.clarke@normation.com>
# Version 0.2 (07/2013):
# - Add support for checking the "disable-agent" flag file
# Author: Jonathan Clarke <jonathan.clarke@normation.com>
#====================================================================
# Source environment variables from /etc/profile
. /etc/profile
# Array indexes
CFEXECD=0
CFSERVERD=1
CFMONITORD=2
CFENGINE_COMMUNITY_NAME[$CFEXECD]="cf-execd"
CFENGINE_COMMUNITY_NAME[$CFSERVERD]="cf-serverd"
CFENGINE_COMMUNITY_NAME[$CFMONITORD]="cf-monitord"
#====================================================================
# Default parameters (if /etc/default/{script_name} is not present)
#====================================================================
# Script specific
PROG_NAME=`basename $0 | sed 's/^[KS][0-9][0-9]//'` # For nice messages
OS=`uname -s` # To adapt message printing
MYUID=`id -u` # For UNIX compatibility => modify this command
MYGID=`id -g` # For UNIX compatibility => modify this command
PS_COMMAND="ps -efww" # This ensures full width for ps output but doesn't work on Solaris - use "ps -ef"
SYSLOG_FACILITY="local6"
# CFEngine Community directory and files
CFENGINE_COMMUNITY_PATH="/usr/local/cfengine"
CFENGINE_COMMUNITY_VAR_PATH="/var/cfengine"
CFENGINE_COMMUNITY_RUN[$CFEXECD]="1"
CFENGINE_COMMUNITY_RUN[$CFSERVERD]="1"
CFENGINE_COMMUNITY_RUN[$CFMONITORD]="1"
CFENGINE_COMMUNITY_BIN[$CFEXECD]="$CFENGINE_COMMUNITY_VAR_PATH/bin/cf-execd"
CFENGINE_COMMUNITY_BIN[$CFSERVERD]="$CFENGINE_COMMUNITY_VAR_PATH/bin/cf-serverd"
CFENGINE_COMMUNITY_BIN[$CFMONITORD]="$CFENGINE_COMMUNITY_VAR_PATH/bin/cf-monitord"
CFENGINE_COMMUNITY_PARAMS[$CFEXECD]=""
CFENGINE_COMMUNITY_PARAMS[$CFSERVERD]=""
CFENGINE_COMMUNITY_PARAMS[$CFMONITORD]=""
CFENGINE_COMMUNITY_PID_FILE[$CFEXECD]="$CFENGINE_COMMUNITY_VAR_PATH/cf-execd.pid"
CFENGINE_COMMUNITY_PID_FILE[$CFSERVERD]="$CFENGINE_COMMUNITY_VAR_PATH/cf-serverd.pid"
CFENGINE_COMMUNITY_PID_FILE[$CFMONITORD]="$CFENGINE_COMMUNITY_VAR_PATH/cf-monitord.pid"
RUDDER_DISABLE_AGENT_FLAG_FILE=/opt/rudder/etc/disable-agent
# Other
TIMEOUT="60" # Max time to stop process
# Return functions' value
RETVAL=""
#====================================================================
# Message function
#====================================================================
message() {
# $1: syslog level
# $2: message
if [ $OS = "Linux" ]
then
logger -p "${SYSLOG_FACILITY}.$1" -s -t $PROG_NAME -i "$2"
else
# Try without option -s
logger -p "${SYSLOG_FACILITY}.$1" -t $PROG_NAME -i "$2"
echo "$PROG_NAME: $2"
fi
}
#====================================================================
# Load specific parameters
#====================================================================
if [ -f /etc/default/$PROG_NAME ]
then
. /etc/default/$PROG_NAME
message "info" "[INFO] Using /etc/default/$PROG_NAME for configuration"
else
message "info" "[INFO] Using built-in configuration - this may cause some problems"
fi
#====================================================================
# Initial checks
#====================================================================
# Which daemons are we running?
DAEMONS=""
for daemon in $CFSERVERD $CFMONITORD $CFEXECD; do
if [ "z${CFENGINE_COMMUNITY_RUN[$daemon]}" == "z1" ]; then DAEMONS="${DAEMONS} $daemon"; fi
done
# Make sure the pidfile directory exists with correct permissions
for daemon in ${DAEMONS}; do
piddir=`dirname "${CFENGINE_COMMUNITY_PID_FILE[$daemon]}"`
if [ ! -d "$piddir" ]; then
mkdir -p "$piddir"
fi
done
# Rights to execute binaries
for daemon in ${DAEMONS}
do
if [ ! -x ${CFENGINE_COMMUNITY_BIN[$daemon]} ]
then
message "alert" "[ALERT] can't execute ${CFENGINE_COMMUNITY_NAME[$daemon]}"
exit 1
fi
done
# Is there a work directory?
if [ "$CFENGINE_COMMUNITY_VAR_PATH" -a ! -w "$CFENGINE_COMMUNITY_VAR_PATH" ]
then
message "alert" "[ALERT] can't write to work directory $CFENGINE_COMMUNITY_VAR_PATH"
exit 1
fi
message "info" "[INFO] Using $CFENGINE_COMMUNITY_VAR_PATH for CFEngine workdir"
# Are you root?
if [ $MYUID -ne 0 ]
then
message "alert" "[ALERT] only root can launch CFEngine Community"
exit 1
fi
#====================================================================
# Functions
#====================================================================
start_daemons() {
RET=0
# Check for disable-agent flag file
if [ -f ${RUDDER_DISABLE_AGENT_FLAG_FILE} ]; then
message "alert" "[ALERT] The ${RUDDER_DISABLE_AGENT_FLAG_FILE} flag file is present. The agent cannot be started."
exit 3
fi
# It's time to start the daemons
for daemon in ${DAEMONS}; do
# Presence of PID file
RUNNING_PID=`ps -efww | grep ${CFENGINE_COMMUNITY_BIN[$daemon]} | grep -v grep | tr -s " " | cut -f2 -d " "`
[[ -f ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} ]] && PID=`cat ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}` || PID=42
if [[ $RUNNING_PID -eq $PID ]]
then
message "info" "[INFO] CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} is already running !"
continue
else
# Start message
message "info" "[INFO] Launching CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]}..."
${CFENGINE_COMMUNITY_BIN[$daemon]} ${CFENGINE_COMMUNITY_PARAMS[$daemon]}
# Waiting loop
i=1
start_failed=0
while [ ! -r ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} ]
do
sleep 2
if [ $i -eq $TIMEOUT -o $i -eq `expr $TIMEOUT / 2` ]
then
message "alert" "[ALERT] no PID file for ${CFENGINE_COMMUNITY_NAME[$daemon]} after $i times Trying again..."
${CFENGINE_COMMUNITY_BIN[$daemon]} ${CFENGINE_COMMUNITY_PARAMS[$daemon]}
fi
if [ $i -eq `expr $TIMEOUT + 10` ]
then
message "alert" "[ALERT] no PID file for ${CFENGINE_COMMUNITY_NAME[$daemon]} after $i times"
RET=1
start_failed=1
break
fi
i=`expr $i + 1`
done
if [ ${start_failed} -eq 1 ]; then continue; fi
# Is daemon launched?
PID=`cat ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}`
if [ ! -e /proc/$PID ]
then
message "alert" "[ALERT] daemon ${CFENGINE_COMMUNITY_NAME[$daemon]} not running"
RET=1
continue
else
message "info" "[OK] CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} started after $i times"
fi
fi
done
if [ $RET -ne 0 ]; then exit $RET; fi
}
stop_daemons() {
RET=0
while [[ `$PS_COMMAND | grep ${CFENGINE_COMMUNITY_VAR_PATH}/bin | grep -v grep | wc -l` -gt 0 ]]
do
for daemon in ${DAEMONS}; do
while [[ `$PS_COMMAND | grep ${CFENGINE_COMMUNITY_BIN[$daemon]} | grep -v grep | wc -l` -gt 0 ]]
do
# Stop message
message "info" "[INFO] Halting CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]}..."
# Presence of PID file
# If the pid file is not readable or is empty, kill all process by name
if [ ! -r ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} -o ! -s ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} ]
then
message "info" "[INFO] can't read PID file, not stopping ${CFENGINE_COMMUNITY_NAME[$daemon]}"
RET=1
sleep 2
else
PID=`cat ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}`
kill -INT $PID
# Waiting loop
# i[$daemon]=1
i[$daemon]=`expr ${i[$daemon]} + 1`
while [ -e /proc/$PID ]
do
if [ ${i[$daemon]} -eq $TIMEOUT ]
then
# Timeout
message "alert" "[ALERT] ${CFENGINE_COMMUNITY_NAME[$daemon]} still running (PID $PID), try: $0 forcestop"
exit 1
fi
i[$daemon]=`expr ${i[$daemon]} + 1`
sleep 1
done
message "info" "[OK] CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} stopped after ${i[$daemon]} times"
fi
done
sleep 1
done
done
if [ $RET -ne 0 ]; then return $RET; fi
}
forcestop_daemons() {
RET=0
for daemon in ${DAEMONS}; do
# Check if any process is running
if [ `$PS_COMMAND | grep ${CFENGINE_COMMUNITY_BIN[$daemon]} | grep -v grep | wc -l` -eq 0 ]
then
message "info" "[INFO] Found no CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} processes running"
# Cleanup PID file
rm -f ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}
continue
fi
# Stop message
message "info" "[INFO] Killing CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} with force..."
# Presence of PID file
# If the pid file is not readable or is empty, kill all process by name
if [ ! -r ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} -o ! -s ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} ]
then
# Try a killall
if [ -x /bin/pidof ]
then
/bin/kill -KILL `/bin/pidof ${CFENGINE_COMMUNITY_BIN[$daemon]}`
else
/usr/bin/killall -KILL ${CFENGINE_COMMUNITY_BIN[$daemon]}
fi
if [ $? -eq 0 ]
then
message "info" "[OK] all CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} processes killed with force"
else
message "alert" "[ALERT] Unable to kill CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} with force"
fi
else
PID=`cat ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}`
kill -KILL $PID
if [ $? -eq 0 ]
then
message "info" "[OK] CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} killed with force (PID $PID)"
# Cleanup PID file
rm -f ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}
else
message "alert" "[ALERT] Unable to kill CFEngine Community ${CFENGINE_COMMUNITY_NAME[$daemon]} with force (PID $PID)"
RET=1
continue
fi
fi
done
if [ $RET -ne 0 ]; then exit $RET; fi
}
# Return 0 if all required daemons are running, 1 if any is stopped, 2 if we can't say, 3 if the disable-agent flag is present
daemons_status() {
# Check for disable-agent flag file
if [ -f ${RUDDER_DISABLE_AGENT_FLAG_FILE} ]; then
return 3
fi
for daemon in ${DAEMONS}; do
if [ ! -r ${CFENGINE_COMMUNITY_PID_FILE[$daemon]} ]
then
# Check if any process are running
if [ `$PS_COMMAND | grep ${CFENGINE_COMMUNITY_BIN[$daemon]} | grep -v grep | wc -l` -eq 0 ]
then
return 1
else
return 2
fi
else
PID=`cat ${CFENGINE_COMMUNITY_PID_FILE[$daemon]}`
fi
if [ ! -e /proc/$PID ]
then
return 1
fi
done
return 0
}
display_status() {
# Get status
daemons_status
status=$?
if [ $status -eq 0 ]
then
message "info" "[INFO] All configured CFEngine Community processes are running"
fi
if [ $status -eq 1 ]
then
message "info" "[INFO] At least one configured CFEngine Community process is not running"
fi
if [ $status -eq 2 ]
then
message "info" "[INFO] Unable to determine CFEngine Community processes status"
fi
if [ $status -eq 3 ]
then
message "info" "[INFO] The ${RUDDER_DISABLE_AGENT_FLAG_FILE} flag is present, CFEngine Community is halted"
fi
# Exit with status code
exit ${status}
}
#====================================================================
# Action switch
#====================================================================
case $1 in
start)
start_daemons
;;
stop)
stop_daemons || forcestop_daemons
;;
forcestop)
forcestop_daemons
;;
restart)
stop_daemons
start_daemons
;;
status)
display_status
;;
*)
echo "Usage: $0 {start|stop|forcestop|restart|status}"
exit 1
;;
esac
#====================================================================
# Exit
#====================================================================
exit 0
@peckpeck
Copy link

peckpeck commented Oct 9, 2015

Hi @frbayart can you give us a diff ?
Or tell me the exact version you are using so that I can do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment