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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20