/[gentoo-alt]/trunk/baselayout-prefix/sbin/rc-daemon.sh
Gentoo

Contents of /trunk/baselayout-prefix/sbin/rc-daemon.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1684 - (hide annotations) (download) (as text)
Thu Mar 31 14:11:48 2011 UTC (3 years, 8 months ago) by grobian
File MIME type: text/x-sh
File size: 11028 byte(s)
applied baselayout-1.12.5-prefix-sh.patch
1 grobian 1682 # Copyright 1999-2006 Gentoo Foundation
2     # Distributed under the terms of the GNU General Public License v2
3    
4     # RC functions to work with daemons
5     # Basically we're a fancy wrapper for start-stop-daemon
6     # and should be called as such. This means that our init scripts
7     # should work as is with zero modification :)
8    
9     # Actually, the above is a small as lie we have some init scripts which try to
10     # get start-stop-daemon to launch a shell script. While this does work with
11     # the start-stop-daemon program in /sbin, it does cause a problem for us
12     # when we're testing for the daemon to be running. I (Roy Marples) view this
13     # as behaviour by design as start-stop-daemon should not be used to run shell
14     # scripts!
15    
16     RC_GOT_DAEMON="yes"
17    
18     [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
19     [[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
20    
21     RC_RETRY_KILL="no"
22     RC_RETRY_TIMEOUT=1
23     RC_RETRY_COUNT=5
24     RC_FAIL_ON_ZOMBIE="no"
25     RC_KILL_CHILDREN="no"
26     RC_WAIT_ON_START="0.1"
27    
28     # void rc_shift_args(void)
29     #
30     # Proccess vars - makes things easier by using the shift command
31     # and indirect variables
32     rc_shift_args() {
33     local addvar
34    
35     while [[ $# != "0" ]]; do
36     if [[ $1 != "-"* && -n ${addvar} ]]; then
37     if [[ -z ${!addvar} ]]; then
38     eval "${addvar}=\"$1\""
39     else
40     eval "${addvar}=\"${!addvar} $1\""
41     fi
42     shift
43     continue
44     fi
45     unset addvar
46     case "$1" in
47     -S|--start)
48     stopping=false
49     ;;
50     -K|--stop)
51     stopping=true
52     ;;
53     -n|--name)
54     addvar="name"
55     ;;
56     -x|--exec|-a|--startas)
57     addvar="cmd"
58     ;;
59     -p|--pidfile)
60     addvar="pidfile"
61     ;;
62     --pidfile=*)
63     pidfile="${1##--pidfile=}"
64     ;;
65     --pid=*)
66     pidfile="${1##--pid=}"
67     ;;
68     -R|--retry)
69     unset RC_RETRY_COUNT
70     addvar="RC_RETRY_COUNT"
71     ;;
72     -s|--signal)
73     addvar="signal"
74     ;;
75     -t|--test|-o|--oknodo)
76     nothing=true
77     ;;
78     esac
79     shift
80     done
81    
82     [[ -z ${RC_RETRY_COUNT} ]] && RC_RETRY_COUNT=5
83     }
84    
85     # void rc_setup_daemon_vars(void)
86     #
87     # Setup our vars based on the start-stop-daemon command
88     rc_setup_daemon_vars() {
89     local -a sargs=( "${args%% \'--\' *}" ) eargs=()
90     local x="${args// \'--\' /}" i=
91     [[ ${x} != "${args}" ]] && eargs=( "${args##* \'--\' }" )
92    
93     eval rc_shift_args "${sargs[@]}"
94    
95     [[ -n ${name} ]] && cmd="${name}"
96    
97     # We may want to launch the daemon with a custom command
98     # This is mainly useful for debugging with apps like valgrind, strace
99     local bash_service="$( bash_variable "${SVCNAME}" )"
100     if [[ -n ${RC_DAEMON} ]]; then
101     local -a d=( ${RC_DAEMON} )
102     if ${stopping}; then
103     args="--stop"
104     else
105     args="--start"
106     fi
107    
108     # Add -- or - arguments as s-s-d options
109     j=${#d[@]}
110     for (( i=0; i<j; i++ )); do
111     [[ ${d[i]:0:1} != "-" ]] && break
112     args="${args} ${d[i]}"
113     unset d[i]
114     done
115     d=( "${d[@]}" )
116    
117     eval args=\"${args} --exec '${d[0]}' -- ${d[@]:1} '${cmd}' ${eargs[@]}\"
118     ! ${stopping} && cmd="${d[0]}"
119     fi
120    
121     return 0
122     }
123    
124     # bool rc_try_kill_pid(int pid, char* signal, bool session)
125     #
126     # Repeatedly kill the pid with the given signal until it dies
127     # If session is true then we use tread pid as session and send it
128     # via pkill
129     # Returns 0 if successfuly otherwise 1
130     rc_try_kill_pid() {
131     local pid="$1" signal="${2:-TERM}" session="${3:-false}" i s p e
132    
133     # We split RC_RETRY_TIMEOUT into tenths of seconds
134     # So we return as fast as possible
135     s=$(( ${RC_RETRY_TIMEOUT}/10 )).$(( ${RC_RETRY_TIMEOUT}%10 ))
136    
137     for (( i=0; i<RC_RETRY_COUNT*10; i++ )); do
138     if ${session} ; then
139     if [[ -x /usr/bin/pkill ]]; then
140     pkill "-${signal}" -s "${pid}"
141     pgrep -s "${pid}" >/dev/null || return 0
142     else
143     local pids="$(ps eo pid,sid | sed -n "s/ ${pid}\$//p")"
144     [[ -z ${pids} ]] && return 0
145     kill -s "${signal}" ${pids} 2>/dev/null
146     e=false
147     for p in ${pids}; do
148     if [[ -d "/proc/${p}" ]]; then
149     e=true
150     break
151     fi
152     done
153     ${e} || return 0
154     fi
155     else
156     [[ ${i} == "0" ]] && kill -s "${signal}" "${pid}" 2>/dev/null
157     [[ ! -d "/proc/${pid}" ]] && return 0
158     fi
159     LC_ALL=C /bin/sleep "${s}"
160     done
161    
162     return 1
163     }
164    
165     # bool rc_kill_pid(int pid, bool session)
166     #
167     # Kills the given pid/session
168     # Returns 1 if we fail to kill the pid (if it's valid) otherwise 0
169     rc_kill_pid() {
170     local pid="$1" session="${2:-false}"
171    
172     rc_try_kill_pid "${pid}" "${signal}" "${session}" && return 0
173    
174     [[ ${RC_RETRY_KILL} == "yes" ]] \
175     && rc_try_kill_pid "${pid}" KILL "${session}" && return 0
176    
177     return 1
178     }
179    
180     # char* pidof(char* cmd, ...)
181     #
182     # Returns a space seperated list of pids associated with the command
183     # This is to handle the rpc.nfsd program which acts weird
184     pidof() {
185     local arg args
186    
187     for arg in "$@"; do
188     [[ ${arg##*/} == "rpc.nfsd" ]] && arg="${arg%/*}/nfsd"
189     args="${args} '"${arg}"'"
190     done
191    
192     eval /bin/pidof -x ${args}
193     }
194    
195     # bool is_daemon_running(char* cmd, char* pidfile)
196     #
197     # Returns 0 if the given daemon is running, otherwise 1
198     # If a pidfile is supplied, the pid inside it must match
199     # a pid in the list of pidof ${cmd}
200     is_daemon_running() {
201     local cmd pidfile pids pid
202    
203     if [[ $# == "1" ]]; then
204     cmd="$1"
205     else
206     local i j="$#"
207     for (( i=0; i<j-1; i++ )); do
208     cmd="${cmd} $1"
209     shift
210     done
211     pidfile="$1"
212     fi
213    
214     pids="$( pidof ${cmd} )"
215     [[ -z ${pids} ]] && return 1
216    
217     [[ -s ${pidfile} ]] || return 0
218    
219     read pid < "${pidfile}"
220     pids=" ${pids} "
221     [[ ${pids// ${pid} /} != "${pids}" ]]
222     }
223    
224     # int rc_start_daemon(void)
225     #
226     # We don't do anyting fancy - just pass the given options
227     # to start-stop-daemon and return the value
228     rc_start_daemon() {
229 grobian 1684 eval @GENTOO_PORTAGE_EPREFIX@/sbin/start-stop-daemon "${args}"
230 grobian 1682 local retval="$?"
231    
232     [[ ${retval} != "0" ]] && return "${retval}"
233     [[ ${RC_WAIT_ON_START} == "0" ]] && return "${retval}"
234    
235     # Give the daemon upto 1 second to fork after s-s-d returns
236     # Some daemons like acpid and vsftpd need this when system is under load
237     # Seems to be only daemons that do not create pid files though ...
238     local i=0
239     for ((i=0; i<10; i++)); do
240     is_daemon_running ${cmd} "${pidfile}" && break
241     LC_ALL=C /bin/sleep "0.1"
242     done
243    
244     # We pause for RC_WAIT_ON_START seconds and then
245     # check if the daemon is still running - this is mainly
246     # to handle daemons who launch and then fail due to invalid
247     # configuration files
248     LC_ALL=C /bin/sleep "${RC_WAIT_ON_START}"
249     is_daemon_running ${cmd} "${pidfile}"
250     retval="$?"
251     [[ ${retval} == "0" ]] && return 0
252    
253     # Stop if we can to clean things up
254     [[ -n ${pidfile} ]] && rc_stop_daemon
255    
256     return "${retval}"
257     }
258    
259     # bool rc_stop_daemon(void)
260     #
261     # Instead of calling start-stop-daemon we instead try and
262     # kill the process ourselves and any children left over
263     # Returns 0 if everything was successful otherwise 1
264     rc_stop_daemon() {
265     local pid pids retval="0"
266    
267     if [[ -n ${cmd} ]]; then
268     if ! is_daemon_running ${cmd} "${pidfile}" ; then
269     [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]] && return 1
270     fi
271     pids="$( pidof ${cmd} )"
272     fi
273    
274     if [[ -s ${pidfile} ]]; then
275     read pid < "${pidfile}"
276     # Check that the given program is actually running the pid
277     if [[ -n ${pids} ]]; then
278     pids=" ${pids} "
279     [[ ${pids// ${pid} /} == "${pids}" ]] && return 1
280     fi
281     pids="${pid}"
282     fi
283    
284     # If there's nothing to kill then return without error
285     [[ -z ${pids} ]] && return 0
286    
287     # We may not have pgrep to find our children, so we provide
288     # two methods
289     if [[ ${RC_KILL_CHILDREN} == "yes" ]]; then
290     if [[ -x /usr/bin/pgrep ]]; then
291     pids="${pids} $(pgrep -P "${pids// /,}")"
292     else
293     local npids
294     for pid in ${pids} ; do
295     npids="${npids} $(ps eo pid,ppid | sed -n "s/ ${pid}\$//p")"
296     done
297     pids="${pids} ${npids}"
298     fi
299     fi
300    
301     for pid in ${pids}; do
302     if [[ ${RC_FAIL_ON_ZOMBIE} == "yes" ]]; then
303     ps p "${pid}" &>/dev/null || return 1
304     fi
305    
306     if rc_kill_pid "${pid}" false ; then
307     # Remove the pidfile if the process didn't
308     [[ -f ${pidfile} ]] && rm -f "${pidfile}"
309     else
310     retval=1
311     fi
312    
313     if [[ ${RC_KILL_CHILDREN} == "yes" ]]; then
314     rc_kill_pid "${pid}" true || retval=1
315     fi
316     done
317    
318     return "${retval}"
319     }
320    
321     # void update_service_status(char *service)
322     #
323     # Loads the service state file and ensures that all listed daemons are still
324     # running - hopefully on their correct pids too
325     # If not, we stop the service
326     update_service_status() {
327     local service="$1" daemonfile="${svcdir}/daemons/$1" i
328     local -a RC_DAEMONS=() RC_PIDFILES=()
329    
330     # We only care about marking started services as stopped if the daemon(s)
331     # for it are no longer running
332     ! service_started "${service}" && return
333     [[ ! -f ${daemonfile} ]] && return
334    
335     # OK, now check that every daemon launched is active
336     # If the --start command was any good a pidfile was specified too
337     source "${daemonfile}"
338     for (( i=0; i<${#RC_DAEMONS[@]}; i++ )); do
339     if ! is_daemon_running ${RC_DAEMONS[i]} "${RC_PIDFILES[i]}" ; then
340     if [[ -e "/etc/init.d/${service}" ]]; then
341     ( /etc/init.d/"${service}" stop &>/dev/null )
342     break
343     fi
344     fi
345     done
346     }
347    
348     # int start-stop-daemon(...)
349     #
350     # Provide a wrapper to start-stop-daemon
351     # Return the result of start_daemon or stop_daemon depending on
352     # how we are called
353     start-stop-daemon() {
354     local args="$( requote "$@" )" result i
355     local cmd name pidfile pid stopping signal nothing=false
356     local daemonfile=
357     local -a RC_DAEMONS=() RC_PIDFILES=()
358    
359     if [[ -n ${SVCNAME} ]] ; then
360     daemonfile="${svcdir}/daemons/${SVCNAME}"
361     [[ -e ${daemonfile} ]] && source "${daemonfile}"
362     fi
363    
364     rc_setup_daemon_vars
365    
366     # We pass --oknodo and --test directly to start-stop-daemon and return
367     if ${nothing}; then
368 grobian 1684 eval @GENTOO_PORTAGE_EPREFIX@/sbin/start-stop-daemon "${args}"
369 grobian 1682 return "$?"
370     fi
371    
372     if ${stopping}; then
373     rc_stop_daemon
374     result="$?"
375     if [[ ${result} == "0" && -n ${daemonfile} ]]; then
376     # We stopped the daemon successfully
377     # so we remove it from our state
378     for (( i=0; i<${#RC_DAEMONS[@]}; i++ )); do
379     # We should really check for valid cmd AND pidfile
380     # But most called to --stop only set the pidfile
381     if [[ ${RC_DAEMONS[i]} == "{cmd}" \
382     || ${RC_PIDFILES[i]} == "${pidfile}" ]]; then
383     unset RC_DAEMONS[i] RC_PIDFILES[i]
384     RC_DAEMONS=( "${RC_DAEMONS[@]}" )
385     RC_PIDFILES=( "${RC_PIDFILES[@]}" )
386     break
387     fi
388     done
389     fi
390     else
391     rc_start_daemon
392     result="$?"
393     if [[ ${result} == "0" && -n ${daemonfile} ]]; then
394     # We started the daemon sucessfully
395     # so we add it to our state
396     local max="${#RC_DAEMONS[@]}"
397     for (( i=0; i<${max}; i++ )); do
398     if [[ ${RC_DAEMONS[i]} == "{cmd}" \
399     && ${RC_PIDFILES[i]}="${pidfile}" ]]; then
400     break
401     fi
402     done
403    
404     if [[ ${i} == "${max}" ]]; then
405     RC_DAEMONS[max]="${cmd}"
406     RC_PIDFILES[max]="${pidfile}"
407     fi
408     fi
409     fi
410    
411     # Write the new list of daemon states for this service
412     if [[ ${#RC_DAEMONS[@]} == "0" ]]; then
413     [[ -f ${daemonfile} ]] && rm -f "${daemonfile}"
414     elif [[ -n ${daemonfile} ]] ; then
415     echo "RC_DAEMONS[0]=\"${RC_DAEMONS[0]}\"" > "${daemonfile}"
416     echo "RC_PIDFILES[0]=\"${RC_PIDFILES[0]}\"" >> "${daemonfile}"
417    
418     for (( i=1; i<${#RC_DAEMONS[@]}; i++ )); do
419     echo "RC_DAEMONS[${i}]=\"${RC_DAEMONS[i]}\"" >> "${daemonfile}"
420     echo "RC_PIDFILES[${i}]=\"${RC_PIDFILES[i]}\"" >> "${daemonfile}"
421     done
422     fi
423    
424     return "${result}"
425     }
426    
427     # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20