On Tue, 2005-08-23 at 16:09 +0200, Paul de Vrieze wrote:
> What I would really like to see in the init system is a way that 
> initscripts can check whether the services they are responsible for are 
> still running and then adjust their status accordingly, along with some 
> nice output. This would then allow the execution of rc-status to give 
> proper information of actually running daemons, and the "rc" command the 
> possibility to actually bring online all daemons that should be running.
> 
> Paul
> 

Attached is a patch to baselayout-1.12.0_pre6-r3 that allows this.
Basically when an init script calls start-stop-daemon --start then we
log what it started (and hopefully a pidfile) in
${svcdir}/daemons/${myservice}

When it's status is asked for (either init.d/foo status or rc-status)
then we load this daemon file and check to see if the given daemons are
still running. If not then we call init.d/foo stop. We do this instead
of just marking the daemon as stopped in-case there is any clean-up code
that's needed to be run by the init script.

For this to work well, start-stop-daemon needs to be used correctly, not
just to stop it (like most init scripts seem to). sshd is a popular init
script and on most Gentoo'ers systems, so I've attached a patch so show
how init script should use start-stop-daemon so this works correctly.

What do people think about this? Is this worthfile and fixing all the
init scripts in the tree to use start-stop-daemon correctly AND for
starting up?

Thanks

Roy
--- rc-status	2005-08-01 21:26:00.000000000 +0100
+++ /bin/rc-status	2005-08-31 07:57:15.000000000 +0100
@@ -31,6 +31,7 @@
 
 # grab settings from conf.d/rc
 source /etc/conf.d/rc
+source "${svclib}/sh/rc-daemon.sh"
 
 ################################################################################
 #  Parse command line options                                                  #
@@ -157,10 +158,19 @@
 #  Now collect information about the status of the various services; whether   #
 #  they're started, broken, or failed.  Put all of this into arrays.           #
 ################################################################################
-# Read services from ${svcdir}/{started,failed,broken}
+if [[ -x ${svcdir}/started ]]; then
+    started=$(ls ${svcdir}/started)
+    # If we're root then update service statuses incase any naughty daemons
+    # stopped running without our say so
+    if [[ ${EUID} == 0 ]]; then
+	for service in ${started}; do
+	    update_service_status "${service}"
+	done
+	started=$(ls ${svcdir}/started)
+    fi
+fi
 [[ -x ${svcdir}/starting ]] && starting=$(ls ${svcdir}/starting)
 [[ -x ${svcdir}/inactive ]] && inactive=$(ls ${svcdir}/inactive)
-[[ -x ${svcdir}/started ]] && started=$(ls ${svcdir}/started)
 [[ -x ${svcdir}/stopping ]] && stopping=$(ls ${svcdir}/stopping)
 
 ################################################################################
--- runscript.sh	2005-08-21 18:08:24.000000000 +0100
+++ /sbin/runscript.sh	2005-08-31 07:59:30.000000000 +0100
@@ -413,6 +413,10 @@
 	# to work with the printed " * status:  foo".
 	local efunc="" state=""
 
+	# If we are effectively root, check to see if required daemons are running
+	# and update our status accordingly
+	[[ ${EUID} == 0 ]] && update_service_status "${myservice}"
+
 	if service_starting "${myservice}" ; then
 		efunc="einfo"
 		state="starting"
--- rc-daemon.sh	2005-08-30 07:22:39.000000000 +0100
+++ /lib/rcscripts/sh/rc-daemon.sh	2005-08-31 07:53:14.000000000 +0100
@@ -19,6 +19,7 @@
 RC_GOT_DAEMON="yes"
 
 [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
+[[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
 
 RC_RETRY_KILL="no"
 RC_RETRY_TIMEOUT=1
@@ -285,14 +286,45 @@
 	return "${retval}"
 }
 
+# void update_service_status(char *service)
+#
+# Loads the service state file and ensures that all listed daemons are still
+# running - hopefully on their correct pids too
+# If not, we stop the service
+update_service_status() {
+	local service="$1" daemonfile="${svcdir}/daemons/$1" i
+	local -a RC_DAEMONS=() RC_PIDFILES=()
+
+	# We only care about marking started services as stopped if the daemon(s)
+	# for it are no longer running
+	! service_started "${service}" && return
+	[[ ! -f ${daemonfile} ]] && return
+
+	# OK, now check that every daemon launched is active
+	# If the --start command was any good a pidfile was specified too
+	source "${daemonfile}"
+	for (( i=0; i<[EMAIL PROTECTED]; i++ )); do
+		if ! is_daemon_running ${RC_DAEMONS[i]} "${RC_PIDFILES[i]}" ; then
+			if [[ -e "/etc/init.d/${service}" ]]; then
+				/etc/init.d/"${service}" stop &>/dev/null
+				break
+			fi
+		fi
+	done
+}
+
 # int start-stop-daemon(...)
 #
 # Provide a wrapper to start-stop-daemon
 # Return the result of start_daemon or stop_daemon depending on
 # how we are called
 start-stop-daemon() {
-	local args=$( requote "$@" )
-	local cmd pidfile pid stopping signal nothing=false
+	local args=$( requote "$@" ) result i
+	local cmd pidfile pid stopping signal nothing=false 
+	local daemonfile="${svcdir}/daemons/${myservice}"
+	local -a RC_DAEMONS=() RC_PIDFILES=()
+
+	[[ -e ${daemonfile} ]] && source "${daemonfile}"
 
 	rc_setup_daemon_vars
 
@@ -303,10 +335,49 @@
 	fi
 
 	if ${stopping}; then
-		rc_stop_daemon 
+		rc_stop_daemon
+		result="$?"
+		if [[ ${result} == "0" ]]; then
+			# We stopped the daemon successfully
+			# so we remove it from our state
+			for (( i=0; i<[EMAIL PROTECTED]; i++ )); do
+				# We should really check for valid cmd AND pidfile
+				# But most called to --stop only set the pidfile
+				if [[ ${RC_DAEMONS[i]} == "{cmd}" \
+					|| ${RC_PIDFILES[i]}="${pidfile}" ]]; then
+					unset RC_DAEMONS[i] RC_PIDFILES[i]
+					RC_DAEMONS=( "[EMAIL PROTECTED]" )
+					RC_PIDFILES=( "[EMAIL PROTECTED]" )
+					break
+				fi
+			done
+		fi
 	else
 		rc_start_daemon
+		result="$?"
+		if [[ ${result} == "0" ]]; then
+			# We started the daemon sucessfully
+			# so we add it to our state
+			local max="[EMAIL PROTECTED]"
+			RC_DAEMONS[max]="${cmd}"
+			RC_PIDFILES[max]="${pidfile}"
+		fi
+	fi
+
+	# Write the new list of daemon states for this service
+	if [[ [EMAIL PROTECTED] == "0" ]]; then
+		[[ -f ${daemonfile} ]] && rm -f "${daemonfile}"
+	else
+		echo "RC_DAEMONS[0]=\"${RC_DAEMONS[0]}\"" > "${daemonfile}"
+		echo "RC_PIDFILES[0]=\"${RC_PIDFILES[0]}\"" >> "${daemonfile}"
+
+		for (( i=1; i<[EMAIL PROTECTED]; i++ )); do
+			echo "RC_DAEMONS[${i}]=\"${RC_DAEMONS[i]}\"" >> "${daemonfile}"
+			echo "RC_PIDFILES[${i}]=\"${RC_PIDFILES[i]}\"" >> "${daemonfile}"
+		done
 	fi
+
+	return "${result}"
 }
 
 # vim:ts=4
--- sshd.orig	2005-08-31 08:07:05.000000000 +0100
+++ sshd	2005-08-31 08:08:05.000000000 +0100
@@ -40,12 +40,14 @@
 start() {
 	checkconfig || return 1
 	ebegin "Starting sshd"
-	/usr/sbin/sshd
+	start-stop-daemon --start --exec /usr/sbin/sshd \
+	    --pidfile /var/run/sshd.pid
 	eend $?
 }
 
 stop() {
 	ebegin "Stopping sshd"
-	start-stop-daemon --stop --quiet --pidfile /var/run/sshd.pid
+	start-stop-daemon --stop --exec /usr/bin/sshd \
+	    --pidfile /var/run/sshd.pid
 	eend $?
 }

Reply via email to