/[vps]/baselayout-vserver/branches/rc-scripts-1_6/sbin/rc-services.sh
Gentoo

Contents of /baselayout-vserver/branches/rc-scripts-1_6/sbin/rc-services.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, 6 months ago) by phreak
File MIME type: text/x-sh
File size: 16329 byte(s)
Merging r1939
1 # Copyright 1999-2004 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header$
4
5 # RC Dependency and misc service functions
6
7 RC_GOT_SERVICES="yes"
8
9 [ "${RC_GOT_FUNCTIONS}" != "yes" ] && source /sbin/functions.sh
10
11 if [ "${RC_GOT_DEPTREE_INFO}" != "yes" ]
12 then
13 if ! /sbin/depscan.sh
14 then
15 echo
16 eerror "Error running '/sbin/depscan.sh'!"
17 eerror "Please correct any problems above."
18
19 exit 1
20 fi
21
22 source "${svcdir}/deptree"
23
24 if [ "${RC_GOT_DEPTREE_INFO}" != "yes" ]
25 then
26 echo
27 eerror "Dependency info is missing! Please run"
28 echo
29 eerror " # /sbin/depscan.sh"
30 echo
31 eerror "to fix this."
32
33 exit 1
34 fi
35 fi
36
37
38 #####################
39 # Internal variables
40 #####################
41
42 # The name of the service whose dependency info we currently have
43 rc_name=
44 # The index of the service whose dependency info we currently have
45 rc_index=0
46 # Our dependency types ...
47 rc_ineed=
48 rc_needsme=
49 rc_iuse=
50 rc_usesme=
51 rc_ibefore=
52 rc_iafter=
53 rc_broken=
54 rc_parallel=
55 rc_mtime=
56
57 ############
58 # Functions
59 ############
60
61 # boot check_mtime(service, mtime)
62 #
63 # Return 0 if 'service's mtime is the same as 'mtime'
64 #
65 check_mtime() {
66 # This one have no 'mtime' ...
67 [ "$1" = "net" ] && return 0
68
69 [ -z "$1" -o -z "$2" ] && return 1
70
71 # Do not fail if there is no script, as virtuals
72 # will then not work ...
73 if [ -e "/etc/init.d/$1" -a -x "/bin/stat" ] && \
74 [ "$(stat -c "%Y" "/etc/init.d/$1" 2>/dev/null)" -ne "$2" ]
75 then
76 return 1
77 fi
78
79 return 0
80 }
81
82 # bool get_service_index(service, index)
83 #
84 # Print the index of 'service'. 'index' is the current index.
85 #
86 get_service_index() {
87 local x=1
88 local index="$2"
89 local myservice="$1"
90
91 if [ -z "$1" -o -z "$2" ]
92 then
93 echo "0"
94 return 1
95 fi
96
97 # Do we already have the index?
98 if [ -n "${index}" ] && [ "${index}" -gt 0 -a \
99 "${myservice}" = "${RC_DEPEND_TREE[${index}]}" ]
100 then
101 echo "${index}"
102 return 0
103 fi
104
105 while [ "${x}" -le "${RC_DEPEND_TREE[0]}" ]
106 do
107 index=$((${x} * ${rc_index_scale}))
108
109 if [ "${myservice}" = "${RC_DEPEND_TREE[${index}]}" ]
110 then
111 echo "${index}"
112 return 0
113 fi
114
115 let "x += 1"
116 done
117
118 echo "0"
119 return 1
120 }
121
122 # bool get_dep_info(service)
123 #
124 # Set the Dependency variables to contain data for 'service'
125 #
126 get_dep_info() {
127 local myservice="$1"
128
129 [ -z "$1" ] && return 1
130
131 # We already have the right stuff ...
132 if [ "${myservice}" = "${rc_name}" -a -n "${rc_mtime}" ] && \
133 check_mtime "${myservice}" "${rc_mtime}"
134 then
135 return 0
136 fi
137
138 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
139 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
140
141 # Does the stored mtime match that of the current rc-script?
142 if ! check_mtime "${myservice}" "${rc_mtime}"
143 then
144 # Nope, check if we already ran depscan.sh
145 source "${svcdir}/deptree"
146 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
147 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
148
149 # Do we have it now?
150 if ! check_mtime "${myservice}" "${rc_mtime}"
151 then
152 # Not? So run depscan.sh ...
153 einfo "Re-caching dependency info (mtimes differ)..." &>/dev/stderr
154 if ! /sbin/depscan.sh &>/dev/null
155 then
156 return 1
157 else
158 # We want to check if we got the dep info later on ...
159 unset RC_GOT_DEPTREE_INFO
160 source "${svcdir}/deptree"
161 # Everything "OK" ?
162 [ "${RC_GOT_DEPTREE_INFO}" != "yes" ] && return 1
163 fi
164
165 rc_index="`get_service_index "${myservice}" "${rc_index}"`"
166 fi
167 fi
168
169 # Verify that we have the correct index (rc_index) ...
170 [ "${rc_index}" -eq 0 ] && return 1
171
172 rc_name="${RC_DEPEND_TREE[${rc_index}]}"
173 rc_ineed="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ineed}))]}"
174 rc_needsme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_needsme}))]}"
175 rc_iuse="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iuse}))]}"
176 rc_usesme="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_usesme}))]}"
177 rc_ibefore="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_ibefore}))]}"
178 rc_iafter="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_iafter}))]}"
179 rc_broken="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_broken}))]}"
180 rc_parallel="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_parallel}))]}"
181 rc_mtime="${RC_DEPEND_TREE[$((${rc_index} + ${rc_type_mtime}))]}"
182
183 return 0
184 }
185
186 # string check_dependency(deptype, service1)
187 #
188 # List all the services that depend on 'service1' of dependency
189 # type 'deptype'
190 #
191 # bool check_dependency(deptype, -t, service1, service2)
192 #
193 # Returns true if 'service2' is a dependency of type 'deptype'
194 # of 'service1'
195 #
196 check_dependency() {
197 local x=
198 local myservice=
199
200 [ -z "$1" -o -z "$2" ] && return 1
201
202 # Set the dependency variables to relate to 'service1'
203 if [ "$2" = "-t" ]
204 then
205 [ -z "$3" -o -z "$4" ] && return 1
206
207 myservice="$3"
208 else
209 myservice="$2"
210 fi
211
212 get_dep_info "${myservice}" >/dev/null || {
213 eerror "Could not get dependency info for \"${myservice}\"!" > /dev/stderr
214 eerror "Please run:" > /dev/stderr
215 echo > /dev/stderr
216 eerror " # /sbin/depscan.sh" > /dev/stderr
217 echo > /dev/stderr
218 eerror "to try and fix this." > /dev/stderr
219 return 1
220 }
221
222 # Do we have valid info for 'deptype' ?
223 [ -z "$(eval echo \${rc_$1})" ] && return 1
224
225 if [ "$2" = "-t" -a -n "$4" ]
226 then
227 # Check if 'service1' have 'deptype' dependency on 'service2'
228 for x in $(eval echo \${rc_$1})
229 do
230 [ "${x}" = "$4" ] && return 0
231 done
232 else
233 # Just list all services that 'service1' have 'deptype' dependency on.
234 eval echo "\${rc_$1}"
235
236 return 0
237 fi
238
239 return 1
240 }
241
242 # Same as for check_dependency, except 'deptype' is set to
243 # 'ineed'. It will return all the services 'service1' NEED's.
244 ineed() {
245 [ -z "$1" ] && return 1
246
247 check_dependency ineed $*
248
249 return $?
250 }
251
252 # Same as for check_dependency, except 'deptype' is set to
253 # 'needsme'. It will return all the services that NEED 'service1'.
254 needsme() {
255 [ -z "$1" ] && return 1
256
257 check_dependency needsme $*
258
259 return $?
260 }
261
262 # Same as for check_dependency, except 'deptype' is set to
263 # 'iuse'. It will return all the services 'service1' USE's.
264 iuse() {
265 [ -z "$1" ] && return 1
266
267 check_dependency iuse $*
268
269 return $?
270 }
271
272 # Same as for check_dependency, except 'deptype' is set to
273 # 'usesme'. It will return all the services that USE 'service1'.
274 usesme() {
275 [ -z "$1" ] && return 1
276
277 check_dependency usesme $*
278
279 return $?
280 }
281
282 # Same as for check_dependency, except 'deptype' is set to
283 # 'ibefore'. It will return all the services that are started
284 # *after* 'service1' (iow, it will start 'service1' before the
285 # list of services returned).
286 ibefore() {
287 [ -z "$1" ] && return 1
288
289 check_dependency ibefore $*
290
291 return $?
292 }
293
294 # Same as for check_dependency, except 'deptype' is set to
295 # 'iafter'. It will return all the services that are started
296 # *before* 'service1' (iow, it will start 'service1' after the
297 # list of services returned).
298 iafter() {
299 [ -z "$1" ] && return 1
300
301 check_dependency iafter $*
302
303 return $?
304 }
305
306 # Same as for check_dependency, except 'deptype' is set to
307 # 'broken'. It will return all the services that 'service1'
308 # NEED, but are not present.
309 broken() {
310 [ -z "$1" ] && return 1
311
312 check_dependency broken $*
313
314 return $?
315 }
316
317 # bool iparallel(service)
318 #
319 # Returns true if the service can be started in parallel.
320 #
321 iparallel() {
322 [ -z "$1" ] && return 1
323
324 if check_dependency parallel -t "$1" "no"
325 then
326 return 1
327 fi
328
329 return 0
330 }
331
332 # bool is_fake_service(service, runlevel)
333 #
334 # Returns ture if 'service' is a fake service in 'runlevel'.
335 #
336 is_fake_service() {
337 local x=
338 local fake_services=
339
340 [ -z "$1" -o -z "$2" ] && return 1
341
342 if [ "$2" != "${BOOTLEVEL}" -a \
343 -e "/etc/runlevels/${BOOTLEVEL}/.fake" ]
344 then
345 fake_services="$(< /etc/runlevels/${BOOTLEVEL}/.fake)"
346 fi
347
348 if [ -e "/etc/runlevels/$2/.fake" ]
349 then
350 fake_services="${fake_services} $(< /etc/runlevels/$2/.fake)"
351 fi
352
353 for x in ${fake_services}
354 do
355 if [ "$1" = "${x##*/}" ]
356 then
357 return 0
358 fi
359 done
360
361 return 1
362 }
363
364 # bool in_runlevel(service, runlevel)
365 #
366 # Returns true if 'service' is in runlevel 'runlevel'.
367 #
368 in_runlevel() {
369 [ -z "$1" -o -z "$2" ] && return 1
370
371 [ -L "/etc/runlevels/$2/$1" ] && return 0
372
373 return 1
374 }
375
376 # bool is_runlevel_start()
377 #
378 # Returns true if it is a runlevel change, and we are busy
379 # starting services.
380 #
381 is_runlevel_start() {
382 [ -d "${svcdir}/softscripts.old" ] && return 0
383
384 return 1
385 }
386
387 # bool is_runlevel_stop()
388 #
389 # Returns true if it is a runlevel change, and we are busy
390 # stopping services.
391 #
392 is_runlevel_stop() {
393 [ -d "${svcdir}/softscripts.new" ] && return 0
394
395 return 1
396 }
397
398 # int start_service(service)
399 #
400 # Start 'service' if it is not already running.
401 #
402 start_service() {
403 local retval=0
404
405 [ -z "$1" ] && return 1
406
407 if ! service_started "$1"
408 then
409 if is_fake_service "$1" "${SOFTLEVEL}"
410 then
411 mark_service_started "$1"
412 else
413 (. /sbin/runscript.sh "/etc/init.d/$1" start)
414 retval="$?"
415 return "${retval}"
416 fi
417 fi
418
419 return 0
420 }
421
422 # int stop_service(service)
423 #
424 # Stop 'service' if it is not already running.
425 #
426 stop_service() {
427 local retval=0
428
429 [ -z "$1" ] && return 1
430
431 if service_started "$1"
432 then
433 if is_runlevel_stop
434 then
435 if is_fake_service "$1" "${OLDSOFTLEVEL}"
436 then
437 mark_service_stopped "$1"
438 return 0
439 fi
440 else
441 if is_fake_service "$1" "${SOFTLEVEL}"
442 then
443 mark_service_stopped "$1"
444 return 0
445 fi
446 fi
447
448 (. /sbin/runscript.sh "/etc/init.d/$1" stop)
449 retval="$?"
450 return "${retval}"
451 fi
452
453 return 0
454 }
455
456 # bool mark_service_started(service)
457 #
458 # Mark 'service' as started.
459 #
460 mark_service_started() {
461 [ -z "$1" ] && return 1
462
463 ln -snf "/etc/init.d/$1" "${svcdir}/started/$1"
464
465 return $?
466 }
467
468 # bool mark_service_stopped(service)
469 #
470 # Mark 'service' as stopped.
471 #
472 mark_service_stopped() {
473 [ -z "$1" ] && return 1
474
475 rm -f "${svcdir}/started/$1"
476
477 return $?
478 }
479
480 # bool service_started(service)
481 #
482 # Returns true if 'service' is started
483 #
484 service_started() {
485 [ -z "$1" ] && return 1
486
487 if [ -L "${svcdir}/started/$1" ]
488 then
489 if [ ! -e "${svcdir}/started/$1" ]
490 then
491 rm -f "${svcdir}/started/$1"
492
493 return 1
494 fi
495 return 0
496 fi
497
498 return 1
499 }
500
501 # bool mark_service_failed(service)
502 #
503 # Mark service as failed for current runlevel. Note that
504 # this is only valid on runlevel change ...
505 #
506 mark_service_failed() {
507 [ -z "$1" ] && return 1
508
509 if [ -d "${svcdir}/failed" ]
510 then
511 ln -snf "/etc/init.d/$1" "${svcdir}/failed/$1"
512 return $?
513 fi
514
515 return 1
516 }
517
518 # bool service_failed(service)
519 #
520 # Return true if 'service' have failed during this runlevel.
521 #
522 service_failed() {
523 [ -z "$1" ] && return 1
524
525 if [ -L "${svcdir}/failed/$1" ]
526 then
527 return 0
528 fi
529
530 return 1
531 }
532
533 # bool net_service(service)
534 #
535 # Returns true if 'service' is a service controlling a network interface
536 #
537 net_service() {
538 [ -z "$1" ] && return 1
539
540 if [ "${1%%.*}" = "net" -a "${1##*.}" != "$1" ]
541 then
542 return 0
543 fi
544
545 return 1
546 }
547
548 # bool is_net_up()
549 #
550 # Return true if service 'net' is considered up, else false.
551 #
552 # Notes for RC_NET_STRICT_CHECKING values:
553 # none net is up without checking anything - usefull for vservers
554 # lo Interface 'lo' is counted and if only it is up, net is up.
555 # no Interface 'lo' is not counted, and net is down even with it up,
556 # so there have to be at least one other interface up.
557 # yes All interfaces must be up.
558 is_net_up() {
559 local netcount=0
560
561 case "${RC_NET_STRICT_CHECKING}" in
562 none)
563 return 0
564 ;;
565 lo)
566 netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \
567 egrep -c "\/net\..*$")"
568 ;;
569 *)
570 netcount="$(ls -1 "${svcdir}"/started/net.* 2> /dev/null | \
571 grep -v 'net\.lo' | egrep -c "\/net\..*$")"
572 ;;
573 esac
574
575 # Only worry about net.* services if this is the last one running,
576 # or if RC_NET_STRICT_CHECKING is set ...
577 if [ "${netcount}" -lt 1 -o "${RC_NET_STRICT_CHECKING}" = "yes" ]
578 then
579 return 1
580 fi
581
582 return 0
583 }
584
585 # void schedule_service_startup(service)
586 #
587 # Schedule 'service' for startup, in parallel if possible.
588 #
589 schedule_service_startup() {
590 local count=0
591 local current_job=
592
593 if [ "${RC_PARALLEL_STARTUP}" = "yes" ]
594 then
595 set -m +b
596
597 if [ "$(jobs | grep -c "Running")" -gt 0 ]
598 then
599 if [ "$(jobs | grep -c "Running")" -eq 1 ]
600 then
601 if [ -n "$(jobs)" ]
602 then
603 current_job="$(jobs | awk '/Running/ { print $4}')"
604 fi
605
606 # Wait if we cannot start this service with the already running
607 # one (running one might start this one ...).
608 query_before "$1" "${current_job}" && wait
609
610 elif [ "$(jobs | grep -c "Running")" -ge 2 ]
611 then
612 count="$(jobs | grep -c "Running")"
613
614 # Wait until we have only one service running
615 while [ "${count}" -gt 1 ]
616 do
617 count="$(jobs | grep -c "Running")"
618 done
619
620 if [ -n "$(jobs)" ]
621 then
622 current_job="$(jobs | awk '/Running/ { print $4}')"
623 fi
624
625 # Wait if we cannot start this service with the already running
626 # one (running one might start this one ...).
627 query_before "$1" "${current_job}" && wait
628 fi
629 fi
630
631 if iparallel "$1"
632 then
633 eval start_service "$1" \&
634 else
635 # Do not start with any service running if we cannot start
636 # this service in parallel ...
637 # wait
638
639 start_service "$1"
640 fi
641 else
642 start_service "$1"
643 fi
644
645 # We do not need to check the return value here, as svc_{start,stop}() do
646 # their own error handling ...
647 return 0
648 }
649
650 # bool dependon(service1, service2)
651 #
652 # Does service1 depend (NEED or USE) on service2 ?
653 #
654 dependon() {
655 [ -z "$1" -o -z "$2" ] && return 1
656
657 if ineed -t "$1" "$2" || iuse -t "$1" "$2"
658 then
659 return 0
660 fi
661
662 return 1
663 }
664
665 # string valid_iuse(service)
666 #
667 # This will only give the valid use's for the service
668 # (they must be in the boot or current runlevel)
669 #
670 valid_iuse() {
671 local x=
672 local y=
673
674 for x in $(iuse "$1")
675 do
676 if [ -e "/etc/runlevels/${BOOTLEVEL}/${x}" -o \
677 -e "/etc/runlevels/${mylevel}/${x}" -o \
678 ${x} = "net" ]
679 then
680 echo "${x}"
681 fi
682 done
683
684 return 0
685 }
686
687 # string valid_iafter(service)
688 #
689 # Valid services for current or boot rc level that should start
690 # before 'service'
691 #
692 valid_iafter() {
693 local x=
694
695 for x in $(iafter "$1")
696 do
697 if [ -e "/etc/runlevels/${BOOTLEVEL}/${x}" -o \
698 -e "/etc/runlevels/${mylevel}/${x}" -o \
699 ${x} = "net" ]
700 then
701 echo "${x}"
702 fi
703 done
704
705 return 0
706 }
707
708 # void trace_depend(deptype, service, deplist)
709 #
710 # Trace the dependency tree of 'service' for type 'deptype', and
711 # modify 'deplist' with the info.
712 #
713 trace_depend() {
714 local x=
715 local y=
716 local add=
717
718 [ -z "$1" -o -z "$2" -o -z "$3" ] && return 1
719
720 # Build the list of services that 'deptype' on this one
721 for x in "$("$1" "$2")"
722 do
723 add="yes"
724
725 for y in $(eval echo "\${$3}")
726 do
727 [ "${x}" = "${y}" ] && add="no"
728 done
729
730 [ "${add}" = "yes" ] && eval $(echo "$3=\"\${$3} ${x}\"")
731
732 # Recurse to build a complete list ...
733 trace_depend "$1" "${x}" "$3"
734 done
735
736 return 0
737 }
738
739 # string list_depend_trace(deptype)
740 #
741 # Return resulting list of services for a trace of
742 # type 'deptype' for $myservice
743 #
744 list_depend_trace() {
745 local x=
746 local list=
747
748 [ -z "$1" ] && return 1
749
750 trace_depend "$1" "${myservice}" "list"
751
752 for x in ${list}
753 do
754 echo "${x}"
755 done
756
757 return 0
758 }
759
760 # bool query_before(service1, service2)
761 #
762 # Return true if 'service2' should be started *before*
763 # service1.
764 #
765 query_before() {
766 local x=
767 local list=
768 local netservice="no"
769
770 [ -z "$1" -o -z "$2" ] && return 1
771
772 trace_depend "ineed" "$1" "list"
773
774 for x in $1 ${list}
775 do
776 trace_depend "iuse" "${x}" "list"
777 done
778
779 for x in $1 ${list}
780 do
781 trace_depend "iafter" "${x}" "list"
782 done
783
784 net_service "$2" && netservice="yes"
785
786 for x in ${list}
787 do
788 [ "${x}" = "$2" ] && return 0
789
790 # Also match "net" if this is a network service ...
791 [ "${netservice}" = "yes" -a "${x}" = "net" ] && return 0
792 done
793
794 return 1
795 }
796
797 # bool query_after(service1, service2)
798 #
799 # Return true if 'service2' should be started *after*
800 # service1.
801 #
802 query_after() {
803 local x=
804 local list=
805 local netservice="no"
806
807 [ -z "$1" -o -z "$2" ] && return 1
808
809 trace_depend "needsme" "$1" "list"
810
811 for x in $1 ${list}
812 do
813 trace_depend "usesme" "${x}" "list"
814 done
815
816 for x in $1 ${list}
817 do
818 trace_depend "ibefore" "${x}" "list"
819 done
820
821 net_service "$2" && netservice="yes"
822
823 for x in ${list}
824 do
825 [ "${x}" = "$2" ] && return 0
826
827 # Also match "net" if this is a network service ...
828 [ "${netservice}" = "yes" -a "${x}" = "net" ] && return 0
829 done
830
831 return 1
832 }
833
834
835 # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20