/[vps]/baselayout-vserver/branches/baselayout-1_12/sbin/runscript.sh
Gentoo

Contents of /baselayout-vserver/branches/baselayout-1_12/sbin/runscript.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 203 - (show annotations) (download) (as text)
Wed Jan 11 17:20:37 2006 UTC (12 years, 5 months ago) by phreak
File MIME type: text/x-sh
File size: 16422 byte(s)
Merging r1802
1 #!/bin/bash
2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 # Common functions
6 [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
7
8 # User must be root to run most script stuff (except status)
9 if [[ ${EUID} != 0 ]] && ! [[ $2 == "status" && $# -eq 2 ]] ; then
10 eerror "$0: must be root to run init scripts"
11 exit 1
12 fi
13
14 # State variables
15 svcpause="no"
16 svcrestart="no"
17
18 myscript="$1"
19 if [[ -L $1 && ! -L "/etc/init.d/${1##*/}" ]] ; then
20 myservice="$(readlink $1)"
21 else
22 myservice="$1"
23 fi
24
25 myservice="${myservice##*/}"
26 export SVCNAME="${myservice}"
27 mylevel="$(<${svcdir}/softlevel)"
28
29 svc_trap() {
30 trap 'eerror "ERROR: \"${myservice}\" caught an interrupt"; exit 1' \
31 INT QUIT TSTP
32 }
33
34 # Setup a default trap
35 svc_trap
36
37 # Functions to handle dependencies and services
38 [[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
39 # Functions to control daemons
40 [[ ${RC_GOT_DAEMON} != "yes" ]] && source "${svclib}/sh/rc-daemon.sh"
41
42 # Set $IFACE to the name of the network interface if it is a 'net.*' script
43 if [[ ${myservice%%.*} == "net" && ${myservice##*.} != "${myservice}" ]] ; then
44 IFACE="${myservice##*.}"
45 NETSERVICE="yes"
46 else
47 IFACE=
48 NETSERVICE=
49 fi
50
51 # Source configuration files.
52 # (1) Source /etc/conf.d/net if it is a net.* service
53 # (2) Source /etc/conf.d/${myservice} to get initscript-specific
54 # configuration (if it exists).
55 # (3) Source /etc/rc.conf to pick up potentially overriding
56 # configuration, if the system administrator chose to put it
57 # there (if it exists).
58 if [[ ${NETSERVICE} == "yes" ]] ; then
59 conf="$(add_suffix /etc/conf.d/net)"
60 [[ -e ${conf} ]] && source "${conf}"
61 fi
62 conf="$(add_suffix /etc/conf.d/${myservice})"
63 [[ -e ${conf} ]] && source "${conf}"
64 conf="$(add_suffix /etc/rc.conf)"
65 [[ -e ${conf} ]] && source "${conf}"
66
67 # Call svc_quit if we abort AND we have obtained a lock
68 svcbegun=1
69 service_started "${myservice}"
70 svcstarted=$?
71 svc_quit() {
72 eerror "ERROR: \"${myservice}\" caught an interrupt"
73 if [[ ${svcbegun} == 0 ]] ; then
74 end_service "${myservice}"
75 svcbegun=1
76 fi
77 if [[ ${svcstarted} == 0 ]] ; then
78 mark_service_started "${myservice}"
79 else
80 mark_service_stopped "${myservice}"
81 fi
82 exit 1
83 }
84
85 usage() {
86 local IFS="|"
87 myline="Usage: ${myservice} { $* "
88 echo
89 eerror "${myline}}"
90 eerror " ${myservice} without arguments for full help"
91 }
92
93 stop() {
94 # Return success so the symlink gets removed
95 return 0
96 }
97
98 start() {
99 eerror "ERROR: \"${myservice}\" does not have a start function."
100 # Return failure so the symlink doesn't get created
101 return 1
102 }
103
104 restart() {
105 svc_restart || return $?
106 }
107
108 status() {
109 # Dummy function
110 return 0
111 }
112
113 svc_stop() {
114 local x= mydep= mydeps= retval=0 was_inactive=false
115 local -a servicelist=()
116
117 # Do not try to stop if it had already failed to do so on runlevel change
118 if is_runlevel_stop && service_failed "${myservice}" ; then
119 return 1
120 fi
121
122 if service_stopped "${myservice}" ; then
123 ewarn "WARNING: \"${myservice}\" has not yet been started."
124 return 0
125 fi
126
127 service_inactive "${myservice}" && was_inactive=true
128 if ! mark_service_stopping "${myservice}" ; then
129 ewarn "WARNING: \"${myservice}\" is already stopping."
130 return 0
131 fi
132 # Lock service starting too ...
133 mark_service_starting "${myservice}"
134
135 # Ensure that we clean up if we abort for any reason
136 trap "svc_quit" INT QUIT TSTP
137
138 begin_service "${myservice}"
139 svcbegun=$?
140
141 service_message "Stopping service ${myservice}"
142
143 if in_runlevel "${myservice}" "${BOOTLEVEL}" && \
144 [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
145 ewarn "WARNING: you are stopping a boot service."
146 fi
147
148 if [[ ${svcpause} != "yes" ]] ; then
149 if [[ ${NETSERVICE} == "yes" ]] ; then
150 # A net.* service
151 if in_runlevel "${myservice}" "${BOOTLEVEL}" || \
152 in_runlevel "${myservice}" "${mylevel}" ; then
153 # Only worry about net.* services if this is the last one running,
154 # or if RC_NET_STRICT_CHECKING is set ...
155 if ! is_net_up ; then
156 mydeps="net"
157 fi
158 fi
159
160 mydeps="${mydeps} ${myservice}"
161 else
162 mydeps="${myservice}"
163 fi
164 fi
165
166 # Save the IN_BACKGROUND var as we need to clear it for stopping depends
167 local ib_save="${IN_BACKGROUND}"
168 unset IN_BACKGROUND
169
170 for mydep in ${mydeps} ; do
171 for x in $(needsme "${mydep}") ; do
172 # Service not currently running, continue
173 if service_started "${x}" ; then
174 stop_service "${x}"
175 service_list=( "${service_list[@]}" "${x}" )
176 fi
177 done
178 done
179
180 for x in "${service_list[@]}" ; do
181 wait_service "${x}"
182 if ! service_stopped "${x}" ; then
183 retval=1
184 break
185 fi
186 done
187
188 IN_BACKGROUND="${ib_save}"
189
190 if [[ ${retval} != 0 ]] ; then
191 eerror "ERROR: problems stopping dependent services."
192 eerror " \"${myservice}\" is still up."
193 else
194 # Stop einfo/ebegin/eend from working as parallel messes us up
195 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes"
196
197 # Now that deps are stopped, stop our service
198 ( stop )
199 retval=$?
200
201 # If a service has been marked inactive, exit now as something
202 # may attempt to start it again later
203 if service_inactive "${myservice}" ; then
204 [[ ${svcbegun} == 0 ]] && end_service "${myservice}" 0
205 return 0
206 fi
207 fi
208
209 if [[ ${retval} != 0 ]] ; then
210 # Did we fail to stop? create symlink to stop multible attempts at
211 # runlevel change. Note this is only used at runlevel change ...
212 is_runlevel_stop && mark_service_failed "${myservice}"
213
214 # If we are halting the system, do it as cleanly as possible
215 if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
216 if ${was_inactive} ; then
217 mark_service_inactive "${myservice}"
218 else
219 mark_service_started "${myservice}"
220 fi
221 fi
222
223 service_message "eerror" "FAILED to stop service ${myservice}!"
224 else
225 # If we're stopped from a daemon that sets ${IN_BACKGROUND} such as
226 # wpa_monitor when we mark as inactive instead of taking the down
227 svcstarted=1
228 if ${IN_BACKGROUND:-false} ; then
229 mark_service_inactive "${myservice}"
230 else
231 mark_service_stopped "${myservice}"
232 fi
233 service_message "Stopped service ${myservice}"
234 fi
235
236 if [[ ${svcbegun} == 0 ]] ; then
237 end_service "${myservice}" "${retval}"
238 svcbegun=1
239 fi
240
241 # Reset the trap
242 svc_trap
243
244 return "${retval}"
245 }
246
247 svc_start() {
248 local x= y= retval=0 was_inactive=false startfail="no"
249
250 # Do not try to start if i have done so already on runlevel change
251 if is_runlevel_start && service_failed "${myservice}" ; then
252 return 1
253 fi
254
255 if service_started "${myservice}" ; then
256 ewarn "WARNING: \"${myservice}\" has already been started."
257 return 0
258 elif service_stopping "${myservice}" ; then
259 eerror "ERROR: please wait for \"${myservice}\" to stop first."
260 return 1
261 elif service_inactive "${myservice}" ; then
262 if [[ ${IN_BACKGROUND} != "true" ]] ; then
263 ewarn "WARNING: \"${myservice}\" has already been started."
264 return 0
265 fi
266 fi
267
268 service_inactive "${myservice}" && was_inactive=true
269 if ! mark_service_starting "${myservice}" ; then
270 ewarn "WARNING: \"${myservice}\" is already starting."
271 return 0
272 fi
273
274 # Ensure that we clean up if we abort for any reason
275 trap "svc_quit" INT QUIT TSTP
276
277 begin_service "${myservice}"
278 svcbegun=$?
279
280 service_message "Starting service ${myservice}"
281
282 local startupservices="$(trace_dependencies $(ineed "${myservice}") \
283 $(valid_iuse ${myservice}))"
284 local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
285 $(dolisting "/etc/runlevels/${mylevel}/net.*")"
286 local mynetservice=
287
288 # Start dependencies, if any.
289 # We don't handle "after" deps here as it's the job of rc to start them.
290 for x in ${startupservices} ; do
291 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] && ! is_net_up ; then
292 for y in ${netservices} ; do
293 mynetservice="${y##*/}"
294 if service_stopped "${mynetservice}" ; then
295 start_service "${mynetservice}"
296 fi
297 done
298 elif [[ ${x} != "net" ]] ; then
299 if service_stopped "${x}" ; then
300 start_service "${x}"
301 fi
302 fi
303 done
304
305 # We also wait for any services we're after to finish incase they
306 # have a "before" dep but we don't dep on them.
307 if is_runlevel_start ; then
308 startupservices="${startupservices} $(valid_iafter ${myservice})"
309 fi
310
311 # Wait for dependencies to finish.
312 for x in ${startupservices} ; do
313 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] ; then
314 for y in ${netservices} ; do
315 mynetservice="${y##*/}"
316
317 wait_service "${mynetservice}"
318
319 if ! service_started "${mynetservice}" ; then
320 # A 'need' dependency is critical for startup
321 if ineed -t "${myservice}" "${x}" >/dev/null ; then
322 # Only worry about a net.* service if we do not have one
323 # up and running already, or if RC_NET_STRICT_CHECKING
324 # is set ....
325 if ! is_net_up ; then
326 startfail="yes"
327 fi
328 fi
329 fi
330 done
331 elif [[ ${x} != "net" ]] ; then
332 wait_service "${x}"
333 if ! service_started "${x}" ; then
334 # A 'need' dependacy is critical for startup
335 if ineed -t "${myservice}" "${x}" >/dev/null ; then
336 startfail="yes"
337 fi
338 fi
339 fi
340 done
341
342 if [[ ${startfail} == "yes" ]] ; then
343 eerror "ERROR: Problem starting needed services."
344 eerror " \"${myservice}\" was not started."
345 retval=1
346 elif broken "${myservice}" ; then
347 eerror "ERROR: Some services needed are missing. Run"
348 eerror " './${myservice} broken' for a list of those"
349 eerror " services. \"${myservice}\" was not started."
350 retval=1
351 else
352 (
353 exit() {
354 RC_QUIET_STDOUT="no"
355 eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
356 eerror "This IS a bug, please fix your broken init.d"
357 unset -f exit
358 exit $@
359 }
360 # Stop einfo/ebegin/eend from working as parallel messes us up
361 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes"
362 start
363 )
364 retval=$?
365
366 # If a service has been marked inactive, exit now as something
367 # may attempt to start it again later
368 if service_inactive "${myservice}" ; then
369 [[ ${svcbegun} == 0 ]] && end_service "${myservice}" 1
370 return 1
371 fi
372 fi
373
374 if [[ ${retval} != 0 ]] ; then
375 is_runlevel_start && mark_service_failed "${myservice}"
376
377 # Remove link if service didn't start; but only if we're not booting
378 # If we're booting, we need to continue and do our best to get the
379 # system up.
380 if [[ ${SOFTLEVEL} != "${BOOTLEVEL}" ]] ; then
381 if ${was_inactive} ; then
382 mark_service_inactive "${myservice}"
383 else
384 mark_service_stopped "${myservice}"
385 fi
386 fi
387
388 service_message "eerror" "FAILED to start service ${myservice}!"
389 else
390 svcstarted=0
391 mark_service_started "${myservice}"
392
393 service_message "Service ${myservice} started OK"
394 fi
395
396 if [[ ${svcbegun} == 0 ]] ; then
397 end_service "${myservice}" "${retval}"
398 svcbegun=1
399 fi
400
401 # Reset the trap
402 svc_trap
403
404 return "${retval}"
405 }
406
407 svc_restart() {
408 if ! service_stopped "${myservice}" ; then
409 svc_stop || return "$?"
410 fi
411 svc_start || return "$?"
412 }
413
414 svc_status() {
415 # The basic idea here is to have some sort of consistent
416 # output in the status() function which scripts can use
417 # as an generic means to detect status. Any other output
418 # should thus be formatted in the custom status() function
419 # to work with the printed " * status: foo".
420 local efunc="" state=""
421
422 # If we are effectively root, check to see if required daemons are running
423 # and update our status accordingly
424 [[ ${EUID} == 0 ]] && update_service_status "${myservice}"
425
426 if service_stopping "${myservice}" ; then
427 efunc="eerror"
428 state="stopping"
429 elif service_starting "${myservice}" ; then
430 efunc="einfo"
431 state="starting"
432 elif service_inactive "${myservice}" ; then
433 efunc="ewarn"
434 state="inactive"
435 elif service_started "${myservice}" ; then
436 efunc="einfo"
437 state="started"
438 else
439 efunc="eerror"
440 state="stopped"
441 fi
442 [[ ${RC_QUIET_STDOUT} != "yes" ]] \
443 && ${efunc} "status: ${state}"
444
445 status
446 [[ ${efunc} != "eerror" ]]
447 }
448
449 rcscript_errors="$(bash -n ${myscript} 2>&1)" || {
450 [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2
451 eerror "ERROR: \"${myscript}\" has syntax errors in it; aborting ..."
452 exit 1
453 }
454
455 # set *after* wrap_rcscript, else we get duplicates.
456 opts="start stop restart"
457
458 source "${myscript}"
459
460 # make sure whe have valid $opts
461 if [[ -z ${opts} ]] ; then
462 opts="start stop restart"
463 fi
464
465 svc_homegrown() {
466 local x arg="$1"
467 shift
468
469 # Walk through the list of available options, looking for the
470 # requested one.
471 for x in ${opts} ; do
472 if [[ ${x} == "${arg}" ]] ; then
473 if typeset -F "${x}" &>/dev/null ; then
474 # Run the homegrown function
475 "${x}"
476
477 return $?
478 fi
479 fi
480 done
481 x=""
482
483 # If we're here, then the function wasn't in $opts.
484 [[ -n $* ]] && x="/ $* "
485 eerror "ERROR: wrong args ( "${arg}" ${x})"
486 # Do not quote this either ...
487 usage ${opts}
488 exit 1
489 }
490
491 shift
492 if [[ $# -lt 1 ]] ; then
493 eerror "ERROR: not enough args."
494 usage ${opts}
495 exit 1
496 fi
497 for arg in $* ; do
498 case "${arg}" in
499 --quiet)
500 RC_QUIET_STDOUT="yes"
501 ;;
502 # We check this in functions.sh ...
503 # --nocolor)
504 # RC_NOCOLOR="yes"
505 # ;;
506 --verbose)
507 RC_VERBOSE="yes"
508 ;;
509 esac
510 done
511 for arg in $* ; do
512 case "${arg}" in
513 stop)
514 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
515 rm -f "${svcdir}/restart/${myservice}"
516 fi
517
518 # Stoped from the background - treat this as a restart so that
519 # stopped services come back up again when started.
520 if [[ ${IN_BACKGROUND} == "true" ]] ; then
521 rm -rf "${svcdir}/snapshot/$$"
522 mkdir -p "${svcdir}/snapshot/$$"
523 cp -a "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
524 fi
525
526 svc_stop
527
528 if [[ ${IN_BACKGROUND} == "true" ]] ; then
529 res=
530 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
531 if service_stopped "${x##*/}" ; then
532 res="${res}${x##*/} "
533 fi
534 done
535 [[ -n ${res} ]] && echo "${res}" > "${svcdir}/restart/${myservice}"
536 fi
537 ;;
538 start)
539 svc_start
540 retval=$?
541 if ! is_runlevel_start && [[ -s "${svcdir}/restart/${myservice}" ]] ; then
542 for x in $(trace_dependencies $(< "${svcdir}/restart/${myservice}")) ; do
543 service_stopped "${x}" && start_service "${x}"
544 done
545 fi
546 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
547 rm -f "${svcdir}/restart/${myservice}"
548 fi
549 exit ${retval}
550 ;;
551 needsme|ineed|usesme|iuse|broken)
552 trace_dependencies "-${arg}"
553 ;;
554 status)
555 svc_status
556 ;;
557 zap)
558 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
559 rm -f "${svcdir}/restart/${myservice}"
560 fi
561 if ! service_stopped "${myservice}" ; then
562 einfo "Manually resetting ${myservice} to stopped state."
563 mark_service_stopped "${myservice}"
564 fi
565 end_service "${myservice}"
566 ;;
567 restart)
568 svcrestart="yes"
569
570 # We don't kill child processes if we're restarting
571 # This is especically important for sshd ....
572 RC_KILL_CHILDREN="no"
573
574 # Create a snapshot of started services
575 rm -rf "${svcdir}/snapshot/$$"
576 mkdir -p "${svcdir}/snapshot/$$"
577 cp -a "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
578
579 # Simple way to try and detect if the service use svc_{start,stop}
580 # to restart if it have a custom restart() funtion.
581 if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then
582 if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") || \
583 -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]] ; then
584 echo
585 ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to"
586 ewarn "restart the service in its custom 'restart()' function."
587 ewarn "Run ${myservice} without arguments for more info."
588 echo
589 svc_restart
590 else
591 restart
592 fi
593 else
594 restart
595 fi
596
597 # Restart dependencies as well
598 if service_started "${myservice}" ; then
599 for x in $(trace_dependencies \
600 $(dolisting "${svcdir}/snapshot/$$/") ) ; do
601 if service_stopped "${x##*/}" ; then
602 start_service "${x##*/}"
603 fi
604 done
605 elif service_inactive "${myservice}" ; then
606 res=
607 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
608 if service_stopped "${x##*/}" ; then
609 res="${res}${x##*/} "
610 fi
611 done
612 [[ -n ${res} ]] && echo "${res}" > "${svcdir}/restart/${myservice}"
613 fi
614
615 # Wait for any services that may still be running ...
616 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
617
618 rm -rf "${svcdir}/snapshot/$$"
619 svcrestart="no"
620 ;;
621 pause)
622 svcpause="yes"
623 svc_stop
624 svcpause="no"
625 ;;
626 --quiet|--nocolor)
627 ;;
628 help)
629 exec "${svclib}"/sh/rc-help.sh "${myscript}" help
630 ;;
631 *)
632 # Allow for homegrown functions
633 svc_homegrown ${arg}
634 ;;
635 esac
636 done
637
638 # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20