LSB-ish init script, RFC
Matthew Farrellee
mfarrellee+fedora at redhat.com
Fri Feb 15 14:43:45 UTC 2008
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
>
More information about the fedora-devel-list
mailing list