]> pere.pagekite.me Git - homepage.git/blob - blog/data/2013-11-02-debian-init-d-script.txt
Generated.
[homepage.git] / blog / data / 2013-11-02-debian-init-d-script.txt
1 Title: Debian init.d boot script example for rsyslog
2 Tags: english, debian, bootsystem
3 Date: 2013-11-02 22:40
4
5 <p>If one of the points of switching to a new init system in Debian is
6 <a href="http://thomas.goirand.fr/blog/?p=147">to get rid of huge
7 init.d scripts</a>, I doubt we need to switch away from sysvinit and
8 init.d scripts at all. Here is an example init.d script, ie a rewrite
9 of /etc/init.d/rsyslog:</p>
10
11 <p><pre>
12 #!/lib/init/init-d-script
13 ### BEGIN INIT INFO
14 # Provides: rsyslog
15 # Required-Start: $remote_fs $time
16 # Required-Stop: umountnfs $time
17 # X-Stop-After: sendsigs
18 # Default-Start: 2 3 4 5
19 # Default-Stop: 0 1 6
20 # Short-Description: enhanced syslogd
21 # Description: Rsyslog is an enhanced multi-threaded syslogd.
22 # It is quite compatible to stock sysklogd and can be
23 # used as a drop-in replacement.
24 ### END INIT INFO
25 DESC="enhanced syslogd"
26 DAEMON=/usr/sbin/rsyslogd
27 </pre></p>
28
29 <p>Pretty minimalistic to me... For the record, the original sysv-rc
30 script was 137 lines, and the above is just 15 lines, most of it meta
31 info/comments.</p>
32
33 <p>How to do this, you ask? Well, one create a new script
34 /lib/init/init-d-script looking something like this:
35
36 <p><pre>
37 #!/bin/sh
38
39 # Define LSB log_* functions.
40 # Depend on lsb-base (>= 3.2-14) to ensure that this file is present
41 # and status_of_proc is working.
42 . /lib/lsb/init-functions
43
44 #
45 # Function that starts the daemon/service
46
47 #
48 do_start()
49 {
50 # Return
51 # 0 if daemon has been started
52 # 1 if daemon was already running
53 # 2 if daemon could not be started
54 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
55 || return 1
56 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
57 $DAEMON_ARGS \
58 || return 2
59 # Add code here, if necessary, that waits for the process to be ready
60 # to handle requests from services started subsequently which depend
61 # on this one. As a last resort, sleep for some time.
62 }
63
64 #
65 # Function that stops the daemon/service
66 #
67 do_stop()
68 {
69 # Return
70 # 0 if daemon has been stopped
71 # 1 if daemon was already stopped
72 # 2 if daemon could not be stopped
73 # other if a failure occurred
74 start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
75 RETVAL="$?"
76 [ "$RETVAL" = 2 ] && return 2
77 # Wait for children to finish too if this is a daemon that forks
78 # and if the daemon is only ever run from this initscript.
79 # If the above conditions are not satisfied then add some other code
80 # that waits for the process to drop all resources that could be
81 # needed by services started subsequently. A last resort is to
82 # sleep for some time.
83 start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
84 [ "$?" = 2 ] && return 2
85 # Many daemons don't delete their pidfiles when they exit.
86 rm -f $PIDFILE
87 return "$RETVAL"
88 }
89
90 #
91 # Function that sends a SIGHUP to the daemon/service
92 #
93 do_reload() {
94 #
95 # If the daemon can reload its configuration without
96 # restarting (for example, when it is sent a SIGHUP),
97 # then implement that here.
98 #
99 start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
100 return 0
101 }
102
103 SCRIPTNAME=$1
104 scriptbasename="$(basename $1)"
105 echo "SN: $scriptbasename"
106 if [ "$scriptbasename" != "init-d-library" ] ; then
107 script="$1"
108 shift
109 . $script
110 else
111 exit 0
112 fi
113
114 NAME=$(basename $DAEMON)
115 PIDFILE=/var/run/$NAME.pid
116
117 # Exit if the package is not installed
118 #[ -x "$DAEMON" ] || exit 0
119
120 # Read configuration variable file if it is present
121 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
122
123 # Load the VERBOSE setting and other rcS variables
124 . /lib/init/vars.sh
125
126 case "$1" in
127 start)
128 [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
129 do_start
130 case "$?" in
131 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
132 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
133 esac
134 ;;
135 stop)
136 [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
137 do_stop
138 case "$?" in
139 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
140 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
141 esac
142 ;;
143 status)
144 status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
145 ;;
146 #reload|force-reload)
147 #
148 # If do_reload() is not implemented then leave this commented out
149 # and leave 'force-reload' as an alias for 'restart'.
150 #
151 #log_daemon_msg "Reloading $DESC" "$NAME"
152 #do_reload
153 #log_end_msg $?
154 #;;
155 restart|force-reload)
156 #
157 # If the "reload" option is implemented then remove the
158 # 'force-reload' alias
159 #
160 log_daemon_msg "Restarting $DESC" "$NAME"
161 do_stop
162 case "$?" in
163 0|1)
164 do_start
165 case "$?" in
166 0) log_end_msg 0 ;;
167 1) log_end_msg 1 ;; # Old process is still running
168 *) log_end_msg 1 ;; # Failed to start
169 esac
170 ;;
171 *)
172 # Failed to stop
173 log_end_msg 1
174 ;;
175 esac
176 ;;
177 *)
178 echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
179 exit 3
180 ;;
181 esac
182
183 :
184 </pre></p>
185
186 <p>It is based on /etc/init.d/skeleton, and could be improved quite a
187 lot. I did not really polish the approach, so it might not always
188 work out of the box, but you get the idea. I did not try very hard to
189 optimize it nor make it more robust either.</p>
190
191 <p>A better argument for switching init system in Debian than reducing
192 the size of init scripts (which is a good thing to do anyway), is to
193 get boot system that is able to handle the kernel events sensibly and
194 robustly, and do not depend on the boot to run sequentially. The boot
195 and the kernel have not behaved sequentially in years.</p>