#!/bin/sh # # Description: Control services under daemontools # # Author: Philip Gwyn # Support: philip@awale.qc.ca # License: GNU General Public License (GPL) # Copyright: (C) 2007 Philp Gwyn / Awalé. # # # OCF_RESKEY_service : the name of the service's sub-directory # OCF_RESKEY_delay : Time (in seconds) to let the process start # OCF_RESKEY_process : name of a command that shows that the service is active # # set -x # Directory that daemontools is installed in DTDIR="" HADIR=/etc/ha.d . $HADIR/shellfuncs if [ -d "$DTDIR/service" ] ; then true # Normaly it goes in / (put "") but I HATE that, so i use /var/daemontools elif [ -d "/var/daemontools/service" ] ; then DTDIR="/var/daemontools" else ha_log "ERROR Can't find daemontools service directory" exit 1 fi DTSERVICE="$DTDIR/service" SVC="$DTDIR/command/svc" SVSTAT="$DTDIR/command/svstat" ############################################################### #### Simple usage statement usage() { echo "Usage: $0 [] {start|stop|status|restart}" } ############################################################### #### Find out if the service is running is_up() { T=$($SVSTAT $SERVICEDIR) if [ $? -ne 0 ] ; then # failed return 0 fi echo $T | grep "$SERVICEDIR: up " 2>/dev/null >/dev/null if [ $? -ne 0 ] ; then # failed return 0 fi return 1 } #### Look in ps -e too find if there is a $PROCESS running. #### This differs from is_up(), in that svc could claim a process is down #### but not all the processes exited. This happens if the process doesn't #### handle TERM properly. For instance if it doesn't propagate it to any #### child processes. #### If PROCESS isn't configed, use is_up() is_active() { if [ "$PROCESS" ] ; then PS=$(ps -e) echo $PS | grep -- $PROCESS 2>/dev/null >/dev/null if [ $? -ne 0 ] ; then # the process isn't running return 0 fi return 1 fi is_up return $? } ##### Make sure a process is running ##### This is different from being active; is it responding to requests? ##### This is application-specific is_running() { if [ "$VERIFY" = "" ] ; then # no verification to be done return 1 fi type=${VERIFY/:[[:digit:]]*/} port=${VERIFY/[[:alnum:]]*:/} ha_log "INFO Verify type=$type port=$port" if [ "$type" = "http" ] ; then is_running_http $port elif [ "$type" = "IKC" ] ; then is_running_ikc $port else ha_log "ERROR Unknown monitor type $type" return 0 fi } ##### Test if a web server is running is_running_http () { port=$1 ret=$(echo -e "GET / HTTP/1.1\nHost: localhost\n\n" | \ nc -w 10 localhost $port 2>&1 >/dev/null ) if [ $? -ne 0 ] ; then ha_log "ERROR $ret" return 0 fi return 1 } is_running_ikc () { export IKC_port=$1 perl << 'PERL' use strict; use warnings; use POSIX qw( strftime ); use POE::Component::IKC::ClientLite; sub ha_log { my $msg = join '', @_; print STDERR strftime $ENV{HA_DATEFMT}, localtime; print STDERR $msg; print STDERR "\n" unless $msg =~ /\n$/; } sub ha_die { ha_log @_; exit 1; } my $port=$ENV{IKC_port}; ha_die "ERROR we need IKC_port" unless $port; my $poe = POE::Component::IKC::ClientLite->spawn( ip=>'127.0.0.1', port=>$port, timeout=>10, connect_timeout=>10 ); ha_die "ERROR Unable to connect to 127.0.0.1:$port: ", POE::Component::IKC::ClientLite::error unless $poe; my $pong = $poe->call( "IKC/ping" ); ha_log "INFO ikc://127.0.0.1:33100/IKC/ping responded $pong"; exit( $pong eq 'PONG' ? 0 : 1 ); PERL ret=$? unset IKC_port if [ $ret -ne 0 ] ; then return 0 else return 1 fi } ############################################################### ##### Wait $DELAY seconds for is_active() to become $want : ##### 1 = process exists ##### 0 = process doesn't exist ##### is_active is polled every $DELAY seconds wait_active() { want=$1 is_active if [ $? -eq $want ] ; then return 1 fi if [ "${DELAY:-0}" -gt 0 ] ; then waiting_for=$PROCESS if [ "$waiting_for" = "" ] ; then waiting_for=service fi ha_log "INFO $SERVICE: Giving $waiting_for $DELAY seconds" end=$(expr `date +%s` + $DELAY) is_active until [ $? -eq $want ] ; do ha_log "INFO $SERVICE: Waiting for $waiting_for" sleep 1 [ $end -lt $(date +%s) ] && return 0 is_active done fi return 1 } ############################################################### kill_off() { sig=$1 is_active if [ $? -eq 1 ] ; then ha_log "ERROR $SERVICE: Stopping with killall -$sig $PROCESS" killall -$sig $PROCESS return 1 fi return 0 } ############################################################### #### Check params check() { if [ ! -d "$SERVICEDIR" -o ! -x "$SERVICEDIR/run" ] ; then ha_log "ERROR $SERVICE: Doesn't look like a daemontools service ($SERVICEDIR)" exit 6 fi } validate_all() { if [ ! -d "$SERVICEDIR" -o ! -x "$SERVICEDIR/run" ] ; then exit 2 fi } ############################################################### #### Start a service start() { is_up if [ $? -eq 0 ] ; then touch $SERVICEDIR/down ha_log "INFO $SERVICE: Starting" ha_log "DEBUG $SERVICE: $SVC -o $SERVICEDIR" $SVC -o $SERVICEDIR fi wait_active 1 is_up || is_active if [ $? -eq 0 ] ; then ha_log "ERROR $SERVICE: Startup failed!" return 7 fi } ############################################################### #### Stop a service stop() { is_up if [ $? -eq 1 ] ; then ha_log "INFO $SERVICE: Stoping" ha_log "DEBUG $SERVICE: $SVC -d $SERVICEDIR" $SVC -d $SERVICEDIR touch $SERVICEDIR/down fi wait_active 0 if [ "$PROCESS" ] ; then kill_off 15 if [ $? -eq 1 ] ; then wait_active 0 kill_off 9 if [ $? -eq 1 ] ; then wait_active 0 fi fi fi is_up || is_active if [ $? -eq 1 ] ; then ha_log "ERROR $SERVICE: Stop failed!" return 3 fi } ############################################################### #### reload () { is_up if [ $? -eq 1 ] ; then is_active if [ $? -eq 1 ] ; then if [ "$PROCESS" ] ; then ha_log "INFO: $PROCESS: Sending SIGHUP" killall -HUP $PROCESS else ha_log "INFO: $SERVICE: Sending SIGHUP to service" $SVC -h $SERVICEDIR fi return 0 fi fi return 7 } ############################################################### #### Status of a service status() { # ha_log "meta_interval=${OCF_RESKEY_CRM_meta_interval}" is_up if [ $? -eq 1 ] ; then is_active if [ $? -eq 1 ] ; then is_running if [ $? -eq 1 ] ; then # ha_log "INFO $SERVICE is running" echo "$SERVICE is running" return 0 else echo "$SERVICE is active but not running" ha_log "INFO $SERVICE is active but not running" fi fi return 1 fi # daemontools claims the service is down... but maybe it's still # exiting is_active if [ $? -eq 1 ] ; then # ha_log "INFO $SERVICE is down" echo "$SERVICE is down but process is active" ha_log "INFO $SERVICE is down but process is active" return 1 fi echo "$SERVICE is stopped" ha_log "INFO $SERVICE is stopped" return 7 } ############################################################### meta_data() { cat < 1.0 Manages daemontool services. http://cr.yp.to/daemontools.html Manages daemontool services. Service name Name of the service to manage. Must be a directory under $DTDIR and contain an executable run command. Delay Delay allowed for a service to start or stop. In seconds. Process name Name of a process to check to see if the service is active. Application specific verification Names the application-specific verification that must be done. Just because process is running doesn't mean it is working. END } ############################################################### #### Parse the params SERVICE=$OCF_RESKEY_service DELAY=${OCF_RESKEY_delay:-10} PROCESS=${OCF_RESKEY_process} VERIFY=${OCF_RESKEY_verify} SERVICEDIR="$DTSERVICE/$SERVICE" ############################################################### #### Run the command # ha_log "INFO $SERVICEDIR ($1)" _status=0 case "$1" in start) check start _status=$? ;; stop) check stop _status=$? ;; restart|reset) check stop start _status=$? ;; reload) check reload _status=$? ;; monitor|status) check status _status=$? ;; meta-data) meta_data ;; validate-all) validate_all ;; *) usage >&2 _status=1 ;; esac exit $_status