I went a little overboard on the || && shortcutting. "[ X ] || ( Y &&
exit )" will do Y and not exit, should be "if [ ! X ]; then Y ; exit ; fi"
Best,
matt
Matthew Farrellee wrote:
While trying to write an LSB init script for the condor package, I ran
across PackagingDrafts/SysVInitScript [1]. It has a very nice template
for an init script. But, first, it wasn't quite sufficient for my
service, and, second, it didn't exactly follow the Initial Actions [2],
which is nearly verbatim the LSB Core 3.2 Init Script Actions [3].
First, it wasn't sufficient for my service because anyone can run a copy
of my service. They just have to have their own config file. Think of it
like having both a system httpd, listening on port 80, and a user httpd,
listening on port 1134. Both process names can easily be "httpd". This
is a problem because /etc/init.d/functions' status() uses pidof, which
can find a user's process and confuse it with a system process. This
means running "service blah start" can silently fail because the init
script thinks the service is already running, when only the user's copy
of the service is running. To get around this I implemented my own
rh_status, calling it pid_status, that uses a pidfile to determine if
the service is running.
Second, the template init script doesn't quite follow the Initial Action
description for "restart". It always calls "stop" even if the service is
already stopped. It also doesn't always print error messages on errors,
such as reload when the service is not running or when the executable is
missing during restart/stop.
Below is a template init script, based on the one already in the wiki,
that solves the issues above. I'd appreciate feedback on how it could be
improved. Maybe it could be added to the wiki as an additional template
for services that create pidfiles when they start.
Best,
matt
[1] http://fedoraproject.org/wiki/PackagingDrafts/SysVInitScript
[2]
http://fedoraproject.org/wiki/PackagingDrafts/SysVInitScript#head-2a29ef136c4702a14dcf6127e3b7d6ff558817b9
[3]
http://refspecs.linux-foundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
template.init:
#!/bin/sh
#
# <daemonname> <summary>
#
# chkconfig: <default runlevel(s)> <start> <stop>
# description: <description, split multiple lines with \
# a backslash>
### BEGIN INIT INFO
# Provides:
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start:
# Default-Stop:
# Short-Description:
# Description:
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
exec="/path/to/<daemonname>"
prog="<service name>"
config="<path to major config file>"
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
pidfile=/var/run/$prog.pid
start() {
echo -n $"Starting $prog: "
# $prog must create proper /var/run/$prog.pid
# start $prog, often: daemon --pidfile $pidfile $exec
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $lockfile
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
# stop $prog, often: killproc -p $pidfile $prog
RETVAL=$?
echo
# also rm -f $pidfile, if $prog doesn't do it itself
[ $RETVAL -eq 0 ] && rm -f $lockfile
return $RETVAL
}
reload() {
echo -n $"Reloading $prog: "
# tell $prog to reload its config
RETVAL=$?
echo
return $RETVAL
}
force_reload() {
echo -n $"Reloading $prog: "
# tell $prog to reload its config, or just restart it
RETVAL=$?
echo
return $RETVAL
}
#
# Determine if a process is running only by looking in a pidfile.
# There is no use of pidof, which can find processes that are not
# started by this script.
#
# ASSUMPTION: The pidfile will exist if the process does, see false
# negative warning.
#
# WARNING: A false positive is possible if the process that dropped
# the pid file has crashed and the pid has been recycled. A false
# negative is possible if the process has not yet dropped the pidfile,
# or it contains the incorrect pid.
#
# Usage: pid_status <pidfile> <lockfile>
# Result: 0 = pid exists
# 1 = pid does not exist, but pidfile does
# 2 = pid does not exist, but lockfile does
# 3 = pidfile does not exist, thus pid does not exist
# 4 = status unknown
#
pid_status() {
if [ -f $1 ]; then
# this can fail if we're not privileged
pid=`cat $1` &>/dev/null
if [ $? -ne 0 -o -z "$pid" ]; then
echo $? $pid
return 4
fi
ps $pid &>/dev/null
if [ $? -ne 0 ]; then
if [ -e $2 ]; then
return 2
fi
return 1
fi
return 0
fi
return 3
}
pid_status $pidfile $lockfile
running=$?
if [ "$1" != "status" ]; then
# Report that $exec does not exist, or is not executable
[ -x $exec ] || (echo $"$0: error: program not installed" && exit 5)
# Report that $prog's config does not exist
[ -f $config ] || (echo $"$0: error: program not configured" && exit 6)
[ $running -eq 4 ] && echo $"$0: error: insufficient privileges" &&
exit 7
fi
case "$1" in
start)
[ $running -eq 0 ] && exit 0
start
RETVAL=$?
;;
stop)
[ $running -eq 0 ] || exit 0
stop
RETVAL=$?
;;
restart)
[ $running -eq 0 ] && stop
start
RETVAL=$?
;;
try-restart)
[ $running -eq 0 ] || exit 0
stop
start
RETVAL=$?
;;
reload)
[ $running -eq 0 ] || (echo $"$0: error: $prog is not running" &&
exit 7)
reload
RETVAL=$?
;;
force-reload)
[ $running -eq 0 ] || (echo $"$0: error: $prog is not running" &&
exit 7)
force_reload
RETVAL=$?
;;
status)
if [ $running -ne 0 ]; then
case "$running" in
1) echo $"$prog dead but pid file exists" ;;
2) echo $"$prog dead but subsys locked" ;;
3) echo $"$prog is stopped" ;;
4) echo $"$prog status is unknown" ;;
esac
exit $running
fi
# WARNING: status uses pidof and may find more pids than it
# should.
status -p $pidfile $prog
RETVAL=$?
;;
*)
echo $"Usage: $0
{start|stop|restart|try-restart|reload|force-reload|status}"
RETVAL=2
esac
exit $RETVAL
--
fedora-devel-list mailing list
fedora-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/fedora-devel-list