/[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 206 - (show annotations) (download) (as text)
Sun Jan 15 10:27:03 2006 UTC (8 years, 6 months ago) by phreak
File MIME type: text/x-sh
File size: 17491 byte(s)
Merging r1822 for branches/baselayout-1_12
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 service_started "${myservice}"
69 svcstarted="$?"
70 service_inactive "${myservice}"
71 svcinactive="$?"
72 svc_quit() {
73 eerror "ERROR: ${myservice} caught an interrupt"
74 end_service "${myservice}"
75 if service_inactive "${myservice}" || [[ ${svcinactive} == 0 ]] ; then
76 mark_service_inactive "${myservice}"
77 elif [[ ${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
106 }
107
108 status() {
109 # Dummy function
110 return 0
111 }
112
113 svc_schedule_restart() {
114 local service="$1" restart="$2"
115 [[ ! -d "${svcdir}/restart/${service}" ]] \
116 && mkdir -p "${svcdir}/restart/${service}"
117 [[ ! -e "${svcdir}/restart/${service}/${restart}" ]] \
118 && ln -snf "/etc/init.d/${service}" \
119 "${svcdir}/restart/${service}/${restart}"
120 }
121
122 svc_start_restart() {
123 [[ ! -d "${svcdir}/restart/${myservice}" ]] && return
124 local x= services= scripts="$(dolisting "${svcdir}/restart/${myservice}/")"
125
126 for x in ${scripts} ; do
127 services="${services} ${x##*/}"
128 done
129
130 for x in $(trace_dependencies "${services}") ; do
131 service_stopped "${x}" && start_service "${x}"
132 rm -f "${svcdir}/restart/${myservice}/${x}"
133 done
134
135 rmdir "${svcdir}/restart/${myservice}"
136 }
137
138 svc_stop() {
139 local x= mydep= mydeps= retval=0
140 local -a servicelist=()
141
142 # Do not try to stop if it had already failed to do so on runlevel change
143 if is_runlevel_stop && service_failed "${myservice}" ; then
144 return 1
145 fi
146
147 if service_stopped "${myservice}" ; then
148 ewarn "WARNING: ${myservice} has not yet been started."
149 return 0
150 fi
151
152 if ! mark_service_stopping "${myservice}" ; then
153 ewarn "WARNING: ${myservice} is already stopping."
154 return 0
155 fi
156 # Lock service starting too ...
157 mark_service_starting "${myservice}"
158
159 # Ensure that we clean up if we abort for any reason
160 trap "svc_quit" INT QUIT TSTP
161
162 begin_service "${myservice}"
163
164 service_message "Stopping service ${myservice}"
165
166 if in_runlevel "${myservice}" "${BOOTLEVEL}" && \
167 [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
168 ewarn "WARNING: you are stopping a boot service."
169 fi
170
171 if [[ ${svcpause} != "yes" ]] ; then
172 if [[ ${NETSERVICE} == "yes" ]] ; then
173 # A net.* service
174 if in_runlevel "${myservice}" "${BOOTLEVEL}" || \
175 in_runlevel "${myservice}" "${mylevel}" ; then
176 # Only worry about net.* services if this is the last one
177 # running or if RC_NET_STRICT_CHECKING is set ...
178 ! is_net_up && mydeps="net"
179 fi
180 mydeps="${mydeps} ${myservice}"
181 else
182 mydeps="${myservice}"
183 fi
184 fi
185
186 # Save the IN_BACKGROUND var as we need to clear it for stopping depends
187 local ib_save="${IN_BACKGROUND}"
188 unset IN_BACKGROUND
189
190 for mydep in ${mydeps} ; do
191 for x in $(needsme "${mydep}") ; do
192 # Service not currently running, continue
193 if service_started "${x}" ; then
194 stop_service "${x}"
195 service_list=( "${service_list[@]}" "${x}" )
196 fi
197 done
198 done
199
200 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
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 " ${myservice} 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 "${myservice}" ; then
239 svcinactive=0
240 end_service "${myservice}" 0
241 return 0
242 fi
243 fi
244
245 if [[ ${retval} != 0 ]] ; then
246 # Did we fail to stop? create symlink to stop multible attempts at
247 # runlevel change. Note this is only used at runlevel change ...
248 is_runlevel_stop && mark_service_failed "${myservice}"
249
250 # If we are halting the system, do it as cleanly as possible
251 if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
252 if [[ ${svcinactive} == 0 ]] ; then
253 mark_service_inactive "${myservice}"
254 else
255 mark_service_started "${myservice}"
256 fi
257 fi
258
259 service_message "eerror" "FAILED to stop service ${myservice}!"
260 else
261 # If we're stopped from a daemon that sets ${IN_BACKGROUND} such as
262 # wpa_monitor when we mark as inactive instead of taking the down
263 svcstarted=1
264 if service_inactive "${myservice}" ; then
265 svcinactive=0
266 else
267 mark_service_stopped "${myservice}"
268 fi
269 service_message "Stopped service ${myservice}"
270 fi
271
272 end_service "${myservice}" "${retval}"
273
274 # Reset the trap
275 svc_trap
276
277 return "${retval}"
278 }
279
280 svc_start() {
281 local x= y= retval=0 startfail= startinactive=
282
283 # Do not try to start if i have done so already on runlevel change
284 if is_runlevel_start && service_failed "${myservice}" ; then
285 return 1
286 fi
287
288 if service_started "${myservice}" ; then
289 ewarn "WARNING: ${myservice} has already been started."
290 return 0
291 elif service_stopping "${myservice}" ; then
292 eerror "ERROR: please wait for ${myservice} to stop first."
293 return 1
294 elif service_inactive "${myservice}" ; then
295 if [[ ${IN_BACKGROUND} != "true" ]] ; then
296 ewarn "WARNING: ${myservice} has already been started."
297 return 0
298 fi
299 fi
300
301 if ! mark_service_starting "${myservice}" ; then
302 ewarn "WARNING: ${myservice} is already starting."
303 return 0
304 fi
305
306 # Ensure that we clean up if we abort for any reason
307 trap "svc_quit" INT QUIT TSTP
308
309 begin_service "${myservice}"
310 service_message "Starting service ${myservice}"
311
312 # Save the IN_BACKGROUND var as we need to clear it for starting depends
313 local ib_save="${IN_BACKGROUND}"
314 unset IN_BACKGROUND
315
316 local startupservices="$(trace_dependencies $(ineed "${myservice}") \
317 $(valid_iuse "${myservice}"))"
318 local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
319 $(dolisting "/etc/runlevels/${mylevel}/net.*")"
320 local startupnetservices=
321
322 # Start dependencies, if any.
323 # We don't handle "after" deps here as it's the job of rc to start them.
324 for x in ${startupservices} ; do
325 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] && ! is_net_up ; then
326 for y in ${netservices} ; do
327 y="${y##*/}"
328 service_stopped "${y}" && start_service "${y}"
329 done
330 elif [[ ${x} != "net" ]] ; then
331 if service_stopped "${x}" ; then
332 start_service "${x}"
333 fi
334 fi
335 done
336
337 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
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 # Wait for dependencies to finish.
346 for x in ${startupservices} ; do
347 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] ; then
348 for y in ${netservices} ; do
349 y="${y##*/}"
350 # Don't wait if it's already been started
351 service_started "${y}" && continue
352 wait_service "${y}"
353 if ! service_started "${y}" ; then
354 # A 'need' dependency is critical for startup
355 if ineed -t "${myservice}" "${x}" >/dev/null ; then
356 if ! is_net_up ; then
357 if service_inactive "${y}" ; then
358 svc_schedule_restart "${y}" "${myservice}"
359 startinactive="${y}"
360 else
361 startfail="${y}"
362 fi
363 break
364 fi
365 fi
366 fi
367 done
368 elif [[ ${x} != "net" ]] ; then
369 # Don't wait if it's already been started
370 service_started "${x}" && continue
371 wait_service "${x}"
372 if ! service_started "${x}" ; then
373 # A 'need' dependacy is critical for startup
374 if ineed -t "${myservice}" "${x}" >/dev/null ; then
375 if service_inactive "${x}" ; then
376 svc_schedule_restart "${x}"
377 startinactive="${x}"
378 else
379 startfail="${x}"
380 fi
381 break
382 fi
383 fi
384 fi
385 done
386
387 if [[ ${startfail} == "yes" ]] ; then
388 eerror "ERROR: Problem starting needed service ${startfail}."
389 eerror " ${myservice} was not started."
390 retval=1
391 elif [[ -n ${startinactive} ]] ; then
392 ewarn "WARNING: ${myservice} is scheduled to start when ${startinactive} has started."
393 retval=1
394 elif broken "${myservice}" ; then
395 eerror "ERROR: Some services needed are missing. Run"
396 eerror " './${myservice} broken' for a list of those"
397 eerror " services. ${myservice} was not started."
398 retval=1
399 else
400 IN_BACKGROUND="${ib_save}"
401 (
402 exit() {
403 RC_QUIET_STDOUT="no"
404 eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
405 eerror "This IS a bug, please fix your broken init.d"
406 unset -f exit
407 exit "$@"
408 }
409 # Stop einfo/ebegin/eend from working as parallel messes us up
410 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes"
411 start
412 )
413 retval="$?"
414
415 # If a service has been marked inactive, exit now as something
416 # may attempt to start it again later
417 if service_inactive "${myservice}" ; then
418 svcinactive=0
419 end_service "${myservice}" 1
420 return 1
421 fi
422 fi
423
424 if [[ ${retval} != 0 ]] ; then
425 # Remove link if service didn't start; but only if we're not booting
426 # If we're booting, we need to continue and do our best to get the
427 # system up.
428 if [[ ${SOFTLEVEL} != "${BOOTLEVEL}" ]] ; then
429 if [[ ${svcinactive} == 0 ]] ; then
430 mark_service_inactive "${myservice}"
431 else
432 mark_service_stopped "${myservice}"
433 fi
434 fi
435
436 if [[ -z ${startinactive} ]] ; then
437 is_runlevel_start && mark_service_failed "${myservice}"
438 service_message "eerror" "FAILED to start service ${myservice}!"
439 fi
440 else
441 svcstarted=0
442 mark_service_started "${myservice}"
443 service_message "Service ${myservice} started OK"
444 fi
445
446 end_service "${myservice}" "${retval}"
447 # Reset the trap
448 svc_trap
449
450 return "${retval}"
451 }
452
453 svc_restart() {
454 if ! service_stopped "${myservice}" ; then
455 svc_stop || return "$?"
456 fi
457 svc_start
458 }
459
460 svc_status() {
461 # The basic idea here is to have some sort of consistent
462 # output in the status() function which scripts can use
463 # as an generic means to detect status. Any other output
464 # should thus be formatted in the custom status() function
465 # to work with the printed " * status: foo".
466 local efunc="" state=""
467
468 # If we are effectively root, check to see if required daemons are running
469 # and update our status accordingly
470 [[ ${EUID} == 0 ]] && update_service_status "${myservice}"
471
472 if service_stopping "${myservice}" ; then
473 efunc="eerror"
474 state="stopping"
475 elif service_starting "${myservice}" ; then
476 efunc="einfo"
477 state="starting"
478 elif service_inactive "${myservice}" ; then
479 efunc="ewarn"
480 state="inactive"
481 elif service_started "${myservice}" ; then
482 efunc="einfo"
483 state="started"
484 else
485 efunc="eerror"
486 state="stopped"
487 fi
488 [[ ${RC_QUIET_STDOUT} != "yes" ]] \
489 && ${efunc} "status: ${state}"
490
491 status
492 # Return 0 if started, otherwise 1
493 [[ ${state} == "started" ]]
494 }
495
496 rcscript_errors="$(bash -n "${myscript}" 2>&1)" || {
497 [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2
498 eerror "ERROR: ${myscript} has syntax errors in it; aborting ..."
499 exit 1
500 }
501
502 # set *after* wrap_rcscript, else we get duplicates.
503 opts="start stop restart"
504
505 source "${myscript}"
506
507 # make sure whe have valid $opts
508 if [[ -z ${opts} ]] ; then
509 opts="start stop restart"
510 fi
511
512 svc_homegrown() {
513 local x arg="$1"
514 shift
515
516 # Walk through the list of available options, looking for the
517 # requested one.
518 for x in ${opts} ; do
519 if [[ ${x} == "${arg}" ]] ; then
520 if typeset -F "${x}" &>/dev/null ; then
521 # Run the homegrown function
522 "${x}"
523
524 return $?
525 fi
526 fi
527 done
528 x=""
529
530 # If we're here, then the function wasn't in $opts.
531 [[ -n $* ]] && x="/ $* "
532 eerror "ERROR: wrong args ( "${arg}" ${x})"
533 # Do not quote this either ...
534 usage ${opts}
535 exit 1
536 }
537
538 shift
539 if [[ $# -lt 1 ]] ; then
540 eerror "ERROR: not enough args."
541 usage ${opts}
542 exit 1
543 fi
544 for arg in $* ; do
545 case "${arg}" in
546 --quiet)
547 RC_QUIET_STDOUT="yes"
548 ;;
549 # We check this in functions.sh ...
550 # --nocolor)
551 # RC_NOCOLOR="yes"
552 # ;;
553 --verbose)
554 RC_VERBOSE="yes"
555 ;;
556 esac
557 done
558 for arg in $* ; do
559 case "${arg}" in
560 stop)
561 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
562 rm -Rf "${svcdir}/restart/${myservice}"
563 fi
564
565 # Stoped from the background - treat this as a restart so that
566 # stopped services come back up again when started.
567 if [[ ${IN_BACKGROUND} == "true" ]] ; then
568 rm -rf "${svcdir}/snapshot/$$"
569 mkdir -p "${svcdir}/snapshot/$$"
570 cp -pP "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
571 fi
572
573 svc_stop
574 retval="$?"
575
576 if [[ ${IN_BACKGROUND} == "true" ]] ; then
577 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
578 if service_stopped "${x##*/}" ; then
579 svc_schedule_restart "${myservice}" "${x##*/}"
580 fi
581 done
582 fi
583
584 exit "${retval}"
585 ;;
586 start)
587 svc_start
588 retval=$?
589 service_started "${myservice}" && svc_start_restart
590 exit "${retval}"
591 ;;
592 needsme|ineed|usesme|iuse|broken)
593 trace_dependencies "-${arg}"
594 ;;
595 status)
596 svc_status
597 ;;
598 zap)
599 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
600 rm -f "${svcdir}/restart/${myservice}"
601 fi
602 if ! service_stopped "${myservice}" ; then
603 einfo "Manually resetting ${myservice} to stopped state."
604 mark_service_stopped "${myservice}"
605 fi
606 end_service "${myservice}"
607 ;;
608 restart)
609 svcrestart="yes"
610
611 # We don't kill child processes if we're restarting
612 # This is especically important for sshd ....
613 RC_KILL_CHILDREN="no"
614
615 # Create a snapshot of started services
616 rm -rf "${svcdir}/snapshot/$$"
617 mkdir -p "${svcdir}/snapshot/$$"
618 cp -pP "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
619
620 # Simple way to try and detect if the service use svc_{start,stop}
621 # to restart if it have a custom restart() funtion.
622 if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then
623 if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") || \
624 -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]] ; then
625 echo
626 ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to"
627 ewarn "restart the service in its custom 'restart()' function."
628 ewarn "Run ${myservice} without arguments for more info."
629 echo
630 svc_restart
631 else
632 restart
633 fi
634 else
635 restart
636 fi
637
638 [[ -e "${svcdir}/restart/${myservice}" ]] \
639 && rm -f "${svcdir}/restart/${myservice}"
640
641 # Restart dependencies as well
642 if service_inactive "${myservice}" ; then
643 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
644 if service_stopped "${x##*/}" ; then
645 svc_schedule_restart "${myservice}" "${x##*/}"
646 fi
647 done
648 elif service_started "${myservice}" ; then
649 svc_start_restart
650 fi
651
652 rm -rf "${svcdir}/snapshot/$$"
653 svcrestart="no"
654 ;;
655 pause)
656 svcpause="yes"
657 svc_stop
658 svcpause="no"
659 ;;
660 --quiet|--nocolor)
661 ;;
662 help)
663 exec "${svclib}"/sh/rc-help.sh "${myscript}" help
664 ;;
665 *)
666 # Allow for homegrown functions
667 svc_homegrown ${arg}
668 ;;
669 esac
670 done
671
672 # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20