/[vps]/baselayout-vserver/trunk/sbin/runscript.sh
Gentoo

Contents of /baselayout-vserver/trunk/sbin/runscript.sh

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20