]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/sh - keep it for file(1) to get bourne shell script result | |
2 | # functions This file contains functions to be used by most or all | |
3 | # shell scripts in the /etc/rc.d/init.d directory. | |
4 | # | |
5 | # $Id$ | |
6 | # | |
7 | # Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org> | |
8 | # Hacked by: Greg Galloway and Marc Ewing | |
9 | # Modified for PLD Linux by: | |
10 | # Marek Obuchowicz <elephant@pld-linux.org> | |
11 | # Arkadiusz Miśkiewicz <misiek@pld-linux.org> | |
12 | # Michał Kochanowicz <mkochano@pld-linux.org> | |
13 | # Łukasz Pawelczyk <havner@pld-linux.org> | |
14 | ||
15 | # First set up a default search path. | |
16 | export PATH="/sbin:/usr/sbin:/bin:/usr/bin" | |
17 | ||
18 | # Set defaults | |
19 | if [ -z "$COLUMNS" -o -z "$LINES" ]; then | |
20 | _setterm() { | |
21 | set -- $(stty size 2>/dev/null) | |
22 | LINES=${LINES:-$1} | |
23 | COLUMNS=${COLUMNS:-$2} | |
24 | } | |
25 | _setterm | |
26 | unset _setterm | |
27 | fi | |
28 | [ -z "$LINES" ] || [ "$LINES" -le 0 ] && LINES=40 | |
29 | [ -z "$COLUMNS" ] || [ "$COLUMNS" -le 0 ] && COLUMNS=80 | |
30 | export LINES COLUMNS | |
31 | INIT_COL=$((COLUMNS - 13)) | |
32 | ||
33 | # Set colors | |
34 | RED=1 | |
35 | GREEN=2 | |
36 | YELLOW=3 | |
37 | BLUE=4 | |
38 | MAGENTA=5 | |
39 | CYAN=6 | |
40 | WHITE=7 | |
41 | NORMAL=15 | |
42 | # Bold definition (second parameter to termput setaf) | |
43 | BOLD=1 | |
44 | NOBOLD=0 | |
45 | # Default colors | |
46 | CBRACKETS="$CYAN" # brackets [ ] color | |
47 | CDONE="$GREEN" # DONE and WORK color | |
48 | CBUSY="$MAGENTA" # BUSY color | |
49 | CFAIL="$RED" # FAIL and DIED color | |
50 | CPOWEREDBY="$CYAN" # "Powered by" color | |
51 | CPLD="$GREEN" # "PLD Linux Distribution" color | |
52 | CI="$RED" # Capital I color (press I to enter interactive startup) | |
53 | CRESMAN="$GREEN" # "Resource Manager" color | |
54 | CHARS="" # Characters displayed on the beginning of show line | |
55 | CCHARS="$NORMAL" # Color of these characters (look at /etc/sysconfig/init-colors.gentoo example) | |
56 | ||
57 | # Source configuration if available - may override default values | |
58 | [ -r /etc/sysconfig/init-colors ] && . /etc/sysconfig/init-colors | |
59 | [ -r /etc/sysconfig/system ] && . /etc/sysconfig/system | |
60 | [ -r /etc/sysconfig/bootsplash ] && . /etc/sysconfig/bootsplash | |
61 | ||
62 | if [ -z "$VSERVER" -o "$VSERVER" = "detect" ]; then | |
63 | { | |
64 | while read _f _ctx; do | |
65 | [ "$_f" = "VxID:" -o "$_f" = "s_context:" ] && break | |
66 | done </proc/self/status | |
67 | } 2>/dev/null | |
68 | if [ -z "$_ctx" -o "$_ctx" = "0" ]; then | |
69 | VSERVER=no | |
70 | else | |
71 | VSERVER=yes | |
72 | fi | |
73 | unset _f _ctx | |
74 | fi | |
75 | ||
76 | # we need to know in functions if we were called from a terminal | |
77 | if [ -z "$ISATTY" ]; then | |
78 | [ -t ] && ISATTY=yes || ISATTY=no | |
79 | export ISATTY | |
80 | fi | |
81 | ||
82 | is_yes() { | |
83 | # Test syntax | |
84 | if [ $# = 0 ]; then | |
85 | msg_usage " is_yes {value}" | |
86 | return 2 | |
87 | fi | |
88 | ||
89 | # Check value | |
90 | case "$1" in | |
91 | yes|Yes|YES|true|True|TRUE|on|On|ON|Y|y|1) | |
92 | # true returns zero | |
93 | return 0 | |
94 | ;; | |
95 | *) | |
96 | # false returns one | |
97 | return 1 | |
98 | ;; | |
99 | esac | |
100 | } | |
101 | ||
102 | is_no() { | |
103 | # Test syntax | |
104 | if [ $# = 0 ]; then | |
105 | msg_usage " is_no {value}" | |
106 | return 2 | |
107 | fi | |
108 | ||
109 | case "$1" in | |
110 | no|No|NO|false|False|FALSE|off|Off|OFF|N|n|0) | |
111 | # true returns zero | |
112 | return 0 | |
113 | ;; | |
114 | *) | |
115 | # false returns one | |
116 | return 1 | |
117 | ;; | |
118 | esac | |
119 | } | |
120 | ||
121 | # checks if file is empty | |
122 | # empty lines and lines beginning with hash are ignored | |
123 | is_empty_file() { | |
124 | [ -s "$1" ] || return 0 | |
125 | grep -vqE "^(#|[[:blank:]]*$)" "$1" && return 1 || return 0 | |
126 | } | |
127 | ||
128 | # returns OK if $1 contains $2 | |
129 | strstr() { | |
130 | local a=$2 | |
131 | [ "${1#*$a*}" = "$1" ] && return 1 | |
132 | return 0 | |
133 | } | |
134 | ||
135 | if is_yes "$FASTRC" || is_yes "$IN_SHUTDOWN"; then | |
136 | RC_LOGGING=no | |
137 | fi | |
138 | ||
139 | if is_no "$RC_LOGGING"; then | |
140 | initlog() { | |
141 | RESULT=0 | |
142 | while [ "$1" != "${1##-}" ]; do | |
143 | case $1 in | |
144 | -c) | |
145 | shift | |
146 | $1 | |
147 | RESULT=$? | |
148 | break | |
149 | ;; | |
150 | *) | |
151 | shift | |
152 | ;; | |
153 | esac | |
154 | done | |
155 | return $RESULT | |
156 | } | |
157 | fi | |
158 | ||
159 | kernelver() { | |
160 | local _x _y _z v old_IFS ver | |
161 | { | |
162 | read _x _y v _z | |
163 | old_IFS=$IFS | |
164 | IFS='.' | |
165 | set -- $v | |
166 | IFS=$old_IFS | |
167 | ||
168 | # strip _* or -* from versions like: "2.6.25_vanilla-1", "2.6.25-1" | |
169 | ver=${3%%[-_]*} | |
170 | ||
171 | while [ ${#ver} -lt 3 ]; do ver="0$ver"; done | |
172 | ver="$2$ver" | |
173 | while [ ${#ver} -lt 6 ]; do ver="0$ver"; done | |
174 | ver="$1$ver" | |
175 | while [ ${#ver} -lt 9 ]; do ver="0$ver"; done | |
176 | echo $ver | |
177 | } < /proc/version | |
178 | } | |
179 | ||
180 | kernelverser() { | |
181 | local _x _y _z v old_IFS ver | |
182 | { | |
183 | read _x _y v _z | |
184 | old_IFS=$IFS | |
185 | IFS='.' | |
186 | set -- $v | |
187 | IFS=$old_IFS | |
188 | ver=$2 | |
189 | while [ ${#ver} -lt 3 ]; do ver="0$ver"; done | |
190 | ver="$1$ver" | |
191 | while [ ${#ver} -lt 6 ]; do ver="0$ver"; done | |
192 | echo $ver | |
193 | } </proc/version | |
194 | } | |
195 | ||
196 | kernelvermser() { | |
197 | local _x _y _z v old_IFS ver | |
198 | { | |
199 | read _x _y v _z | |
200 | old_IFS=$IFS | |
201 | IFS='.' | |
202 | set -- $v | |
203 | IFS=$old_IFS | |
204 | ver="$1$ver" | |
205 | while [ ${#ver} -lt 3 ]; do ver="0$ver"; done | |
206 | echo $ver | |
207 | } </proc/version | |
208 | } | |
209 | ||
210 | # Colors workaround | |
211 | termput() { | |
212 | is_yes "$ISATTY" || return | |
213 | ||
214 | if is_yes "$FASTRC" || is_no "$TPUT"; then | |
215 | case "$1" in | |
216 | hpa) | |
217 | echo -ne "\033[$(($2+1))G" | |
218 | ;; | |
219 | cuu*) | |
220 | echo -ne "\033[${2}A" | |
221 | ;; | |
222 | el) | |
223 | echo -ne "\033[0K" | |
224 | ;; | |
225 | setaf) | |
226 | local ISBOLD | |
227 | if [ -n "$3" ]; then | |
228 | ISBOLD="$3" | |
229 | else | |
230 | ISBOLD="$NOBOLD"; | |
231 | fi | |
232 | is_yes "$COLOR_INIT" && echo -ne "\033[${ISBOLD};3${2}m" | |
233 | ;; | |
234 | op) | |
235 | termput setaf $NORMAL | |
236 | ;; | |
237 | esac | |
238 | else | |
239 | case "$1" in | |
240 | hpa | cuu* | el) | |
241 | tput "$@" | |
242 | ;; | |
243 | setaf) | |
244 | if [ "$3" = "1" ]; then tput bold; else tput sgr0; fi | |
245 | is_yes "$COLOR_INIT" && tput setaf "$2" | |
246 | ;; | |
247 | op) | |
248 | termput setaf $NORMAL | |
249 | ;; | |
250 | esac | |
251 | fi | |
252 | } | |
253 | ||
254 | if [ ! -x /bin/printf ]; then | |
255 | # printf equivalent | |
256 | # FIXME: buggy when single or double quotes in message! | |
257 | printf() { | |
258 | local text m | |
259 | text="$1" | |
260 | shift | |
261 | if [ $# -gt 0 ]; then | |
262 | m="$1" | |
263 | shift | |
264 | while [ $# -gt 0 ]; do | |
265 | m="$m\",\"$1" | |
266 | shift | |
267 | done | |
268 | fi | |
269 | awk "BEGIN {printf \"$text\", \"$m\"; }" | |
270 | } | |
271 | fi | |
272 | ||
273 | # National language support function | |
274 | nls() { | |
275 | local msg_echo nls_domain text message | |
276 | msg_echo='\n' | |
277 | nls_domain="$NLS_DOMAIN" | |
278 | while [ "$1" != "${1##-}" ]; do | |
279 | case "$1" in | |
280 | --nls-domain) | |
281 | shift | |
282 | nls_domain="$1" | |
283 | shift | |
284 | ;; | |
285 | -n) | |
286 | msg_echo='' | |
287 | shift | |
288 | ;; | |
289 | esac | |
290 | done | |
291 | message="$1" | |
292 | shift | |
293 | ||
294 | # empty message, so we return --misiek | |
295 | if [ -z "$message" ]; then | |
296 | echo -en "$msg_echo" | |
297 | return | |
298 | fi | |
299 | ||
300 | if is_yes "$GETTEXT"; then | |
301 | message=$(TEXTDOMAINDIR="/etc/sysconfig/locale" gettext -e --domain="${nls_domain:-rc-scripts}" "$message") | |
302 | fi | |
303 | ||
304 | printf "$message" "$@" | |
305 | echo -en "$msg_echo" | |
306 | } | |
307 | ||
308 | rc_splash() { | |
309 | local action="$1" | |
310 | ||
311 | if ! is_no "$BOOT_SPLASH" && ! is_yes "$VSERVER"; then | |
312 | [ -x /bin/splash ] && /bin/splash "$action" | |
313 | fi | |
314 | ||
315 | : $((progress++)) | |
316 | } | |
317 | ||
318 | msg_network_down() { | |
319 | nls "ERROR: Networking is down. %s can't be run." "$1" >&2 | |
320 | } | |
321 | ||
322 | msg_starting() { | |
323 | show "Starting %s service" "$1" | |
324 | } | |
325 | ||
326 | msg_already_running() { | |
327 | nls "%s service is already running." "$1" | |
328 | } | |
329 | ||
330 | msg_stopping() { | |
331 | show "Stopping %s service" "$1" | |
332 | } | |
333 | ||
334 | msg_not_running() { | |
335 | nls "%s service is not running." "$1" | |
336 | } | |
337 | ||
338 | msg_reloading() { | |
339 | show "Reloading %s service" "$1" | |
340 | } | |
341 | ||
342 | msg_usage() { | |
343 | nls "Usage: %s" "$*" | |
344 | } | |
345 | ||
346 | # Some functions to handle PLD Linux-style messages | |
347 | show() { | |
348 | local text len | |
349 | ||
350 | if is_no "$FASTRC" && is_yes "$GETTEXT"; then | |
351 | text=$(nls -n "$@") | |
352 | else | |
353 | text=$(printf "$@") | |
354 | fi | |
355 | len=${#text} | |
356 | while [ $((len++)) -lt $INIT_COL ]; do | |
357 | text="$text." | |
358 | done | |
359 | if [ -n "$CHARS" ]; then | |
360 | termput setaf $CCHARS | |
361 | echo -n "$CHARS" | |
362 | termput op | |
363 | fi | |
364 | echo -n "$text" | |
365 | } | |
366 | ||
367 | deltext() { | |
368 | termput hpa $INIT_COL | |
369 | } | |
370 | ||
371 | # Displays message in square brackests ("[ DONE ]"). Takes two arguments. | |
372 | # First is the text to display, second is color number to use (argument to | |
373 | # tput setaf). If second argument is not given, default (2, green) will be | |
374 | # used). | |
375 | progress() { | |
376 | local COLOR | |
377 | if [ -n "$2" ]; then | |
378 | COLOR="$2" | |
379 | else | |
380 | COLOR="$CDONE" | |
381 | fi | |
382 | deltext | |
383 | echo -n "$(termput setaf $CBRACKETS)[$(termput setaf $COLOR) $(nls --nls-domain rc-scripts "$1") $(termput setaf $CBRACKETS)]$(termput op)" | |
384 | } | |
385 | ||
386 | busy() { | |
387 | echo -n "$_busy" | |
388 | } | |
389 | ||
390 | ok() { | |
391 | echo "$_ok" | |
392 | } | |
393 | ||
394 | started() { | |
395 | echo "$_started" | |
396 | } | |
397 | ||
398 | fail() { | |
399 | echo "$_fail" | |
400 | return 1 | |
401 | } | |
402 | ||
403 | died() { | |
404 | echo "$_died" | |
405 | return 1 | |
406 | } | |
407 | ||
408 | # Check if $pid (could be plural) are running | |
409 | checkpid() { | |
410 | while [ "$1" ]; do | |
411 | [ -d "/proc/$1" ] && return 0 | |
412 | shift | |
413 | done | |
414 | return 1 | |
415 | } | |
416 | ||
417 | # - outside chroot get only those processes, which are outside chroot. | |
418 | # - inside chroot get only those processes, which are inside chroot. | |
419 | # - don't filter out pids which do not have corresponding running processes (process died etc) | |
420 | # (note: some processes like named are chrooted but run outside chroot) | |
421 | # - do nothing inside vserver | |
422 | filter_chroot() { | |
423 | if is_yes "$VSERVER"; then | |
424 | echo $@ | |
425 | return | |
426 | fi | |
427 | if [ $# -lt 1 -o ! -d /proc/1 ]; then | |
428 | echo $@ | |
429 | return | |
430 | fi | |
431 | local root_dir good_pids="" good_add_pid | |
432 | for root_pid in $@; do | |
433 | root_dir=$(resolvesymlink /proc/${root_pid}/root) | |
434 | if [ -n "$root_dir" ]; then | |
435 | good_add_pid=1 | |
436 | if [ -n "${SYSTEM_CHROOTS}" ]; then | |
437 | for r_dir in ${SYSTEM_CHROOTS}; do | |
438 | echo "$root_dir" | grep -q "^${r_dir}" && good_add_pid=0 | |
439 | done | |
440 | fi | |
441 | [ "$good_add_pid" -eq 1 ] && good_pids="$good_pids $root_pid" | |
442 | elif [ ! -d "/proc/$root_pid" ]; then | |
443 | good_pids="$good_pids $root_pid" | |
444 | fi | |
445 | done | |
446 | echo $good_pids | |
447 | } | |
448 | ||
449 | # Usage run_cmd Message command_to_run | |
450 | run_cmd() { | |
451 | local exit_code errors message force_err | |
452 | local force_err=0 exit_code=0 | |
453 | case "$1" in | |
454 | -a) | |
455 | force_err=1 | |
456 | shift | |
457 | ;; | |
458 | esac | |
459 | message=$1 | |
460 | show "$message"; busy | |
461 | shift | |
462 | cd / | |
463 | if errors=$( | |
464 | export HOME=/tmp TMPDIR=/tmp | |
465 | if is_no "$RC_LOGGING"; then | |
466 | "$@" 2>&1 | |
467 | else | |
468 | initlog -c "$*" 2>&1 | |
469 | fi | |
470 | ); then | |
471 | ok | |
472 | log_success "$1 $message" | |
473 | else | |
474 | fail | |
475 | log_failed "$1 $message" | |
476 | exit_code=1 | |
477 | fi | |
478 | [ -n "$errors" ] && [ $exit_code -eq 1 -o $force_err -eq 1 ] && echo "$errors" | |
479 | return $exit_code | |
480 | } | |
481 | ||
482 | _daemon_set_ulimits() { | |
483 | local opt val ksh=${KSH_VERSION:+1} | |
484 | set -- ${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS} | |
485 | while [ $# -gt 0 ]; do | |
486 | opt=$1 | |
487 | val=$2 | |
488 | if [ "$ksh" ]; then | |
489 | case "$opt" in | |
490 | -Hu) | |
491 | opt=-Hp | |
492 | ;; | |
493 | -Su) | |
494 | opt=-Sp | |
495 | ;; | |
496 | -u) | |
497 | opt=-p | |
498 | ;; | |
499 | esac | |
500 | fi | |
501 | ulimit $opt $val | |
502 | shift 2 | |
503 | done | |
504 | } | |
505 | ||
506 | # A function to start a program (now it's useful on read-only filesystem too) | |
507 | daemon() { | |
508 | local errors="" prog="" end="" waitname="" waittime="" | |
509 | local exit_code=0 | |
510 | local nice=$SERVICE_RUN_NICE_LEVEL | |
511 | local fork user closefds redirfds pidfile makepid chdir=/ | |
512 | ||
513 | # NOTE: if you wonder how the shellish (by syntax) $prog works in ssd mode, | |
514 | # then the answer is: it totally ignores $prog and uses "$@" itself. | |
515 | ||
516 | while [ $# -gt 0 ]; do | |
517 | case $1 in | |
518 | '') | |
519 | msg_usage " daemon [--check] [--user user] [--fork] [--chdir directory] [--closefds] [--redirfds] [--waitforname procname] [--waitfortime seconds] [--pidfile file] [--makepid] [+/-nicelevel] {program} <program args>" | |
520 | return 2 | |
521 | ;; | |
522 | --check) | |
523 | # for compatibility with redhat/mandrake | |
524 | nls "warning: --check option is ignored!" | |
525 | shift | |
526 | ;; | |
527 | --user) | |
528 | shift | |
529 | [ "$1" != "root" ] && prog="/bin/su $1 -s /bin/sh -c \"" | |
530 | user=$1 | |
531 | ;; | |
532 | --fork) | |
533 | fork=1 | |
534 | prog="/usr/bin/setsid sh -c \"" | |
535 | end='&' | |
536 | ;; | |
537 | --chdir) | |
538 | shift | |
539 | chdir=$1 | |
540 | ;; | |
541 | --closefds) | |
542 | closefds=1 | |
543 | ;; | |
544 | --redirfds) | |
545 | redirfds=1 | |
546 | ;; | |
547 | --waitforname) | |
548 | shift | |
549 | waitname="$1" | |
550 | ;; | |
551 | --waitfortime) | |
552 | shift | |
553 | waittime="$1" | |
554 | ;; | |
555 | --pidfile) | |
556 | shift | |
557 | pidfile="$1" | |
558 | case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac | |
559 | ;; | |
560 | --makepid) | |
561 | makepid=1 | |
562 | ;; | |
563 | -*|+*) | |
564 | nice=$1 | |
565 | shift | |
566 | break | |
567 | ;; | |
568 | *) | |
569 | break | |
570 | ;; | |
571 | esac | |
572 | shift | |
573 | done | |
574 | # If command to execute ends with quotation mark, add remaining | |
575 | # arguments and close quotation. | |
576 | if [ "$prog" != "${prog%\"}" ]; then | |
577 | prog="$prog $*$end\"" | |
578 | else | |
579 | prog="$prog $*$end" | |
580 | fi | |
581 | ||
582 | _daemon_set_ulimits | |
583 | ||
584 | [ -z "$DEFAULT_SERVICE_UMASK" ] && DEFAULT_SERVICE_UMASK=022 | |
585 | [ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0 | |
586 | ||
587 | # And start it up. | |
588 | busy | |
589 | cd $chdir | |
590 | [ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS" && echo $$ > "/dev/cpuset/${SERVICE_CPUSET}/tasks" | |
591 | if errors=$( | |
592 | umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK}; | |
593 | export USER=root HOME=/tmp TMPDIR=/tmp | |
594 | nice=${nice:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} | |
595 | nice=${nice:-0} | |
596 | ||
597 | if [ "$closefds" = 1 ]; then | |
598 | exec 1>&- | |
599 | exec 2>&- | |
600 | exec 0>&- | |
601 | elif [ "$redirfds" = 1 ]; then | |
602 | exec 1>/dev/null | |
603 | exec 2>/dev/null | |
604 | exec 0>/dev/null | |
605 | else | |
606 | exec 2>&1 | |
607 | fi | |
608 | ||
609 | if is_no "$RC_LOGGING"; then | |
610 | prog=$1; shift | |
611 | if [ ! -x $prog ]; then | |
612 | logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript" | |
613 | local a o=$IFS | |
614 | IFS=: | |
615 | for a in $PATH; do | |
616 | if [ -x $a/$prog ]; then | |
617 | prog=$a/$prog | |
618 | break | |
619 | fi | |
620 | done | |
621 | IFS=$o | |
622 | fi | |
623 | /sbin/start-stop-daemon -q --start \ | |
624 | --nicelevel $nice \ | |
625 | ${pidfile:+--pidfile $pidfile} \ | |
626 | ${makepid:+--make-pidfile} \ | |
627 | ${user:+--chuid $user} \ | |
628 | ${chdir:+--chdir "$chdir"} \ | |
629 | ${fork:+--background} \ | |
630 | ${waitname:+--name $waitname} \ | |
631 | ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \ | |
632 | --exec "$prog" \ | |
633 | -- ${1:+"$@"} | |
634 | else | |
635 | nice -n $nice initlog -c "$prog" 2>&1 | |
636 | fi | |
637 | ); then | |
638 | ||
639 | if [ -n "$waitname" -a -n "$waittime" ]; then | |
640 | # Save basename. | |
641 | base=${waitname##*/} | |
642 | # Find pid. | |
643 | pid=$(pidofproc "$waitname" "$pidfile") | |
644 | [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile") | |
645 | i=0 | |
646 | while [ "$i" -lt "$waittime" ]; do | |
647 | i=$((i + 1)) | |
648 | checkpid $pid && sleep 1 || break | |
649 | done | |
650 | fi | |
651 | log_success "$1 startup" | |
652 | ok | |
653 | else | |
654 | exit_code=1 | |
655 | fail | |
656 | log_failed "$1 startup" | |
657 | [ -n "$errors" ] && echo >&2 "$errors" | |
658 | fi | |
659 | return $exit_code | |
660 | } | |
661 | ||
662 | # A function to stop a program. | |
663 | killproc() { | |
664 | local notset killlevel base pid pidfile result | |
665 | # Test syntax. | |
666 | if [ $# = 0 ]; then | |
667 | msg_usage " killproc [--pidfile PIDFILE] {program} [-SIGNAME]" | |
668 | return 2 | |
669 | fi | |
670 | ||
671 | while [ "$1" != "${1##-}" ]; do | |
672 | case $1 in | |
673 | --pidfile) | |
674 | pidfile="$2" | |
675 | case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac | |
676 | shift 2 | |
677 | ;; | |
678 | --waitforname) | |
679 | waitname="$2" | |
680 | shift 2 | |
681 | ;; | |
682 | --waitfortime) | |
683 | waittime="$2" | |
684 | shift 2 | |
685 | ;; | |
686 | esac | |
687 | done | |
688 | ||
689 | busy | |
690 | ||
691 | local notset=0 | |
692 | # check for second arg to be kill level | |
693 | if [ -n "$2" ]; then | |
694 | killlevel=$2 | |
695 | else | |
696 | notset=1 | |
697 | fi | |
698 | ||
699 | # experimental start-stop-daemon based killing. | |
700 | # works only with pidfile | |
701 | if is_no "$RC_LOGGING" && [ "$pidfile" ]; then | |
702 | local sig=${killlevel:--TERM} | |
703 | /sbin/start-stop-daemon -q --stop \ | |
704 | --retry ${sig#-}/10/${sig#-}/60/KILL/10 \ | |
705 | -s ${sig#-} \ | |
706 | ${pidfile:+--pidfile $pidfile} | |
707 | result=$? | |
708 | if [ "$result" -eq 0 ]; then | |
709 | ok | |
710 | else | |
711 | fail | |
712 | fi | |
713 | return $result | |
714 | fi | |
715 | ||
716 | ||
717 | # Save basename. | |
718 | base=${1##*/} | |
719 | ||
720 | # Find pid. | |
721 | pid=$(pidofproc "$1" "$pidfile") | |
722 | [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile") | |
723 | ||
724 | # Kill it. | |
725 | if [ -n "$pid" -a "$pid" != "$$" ] && checkpid $pid 2>&1; then | |
726 | if [ "$notset" = "1" ]; then | |
727 | if checkpid $pid 2>&1; then | |
728 | # TERM first, then KILL if not dead | |
729 | kill -TERM $pid | |
730 | usleep 100000 | |
731 | if checkpid $pid && sleep 1 && | |
732 | checkpid $pid && sleep 3 && | |
733 | checkpid $pid; then | |
734 | # XXX: SIGKILL is sent already on 4th second! | |
735 | # HARMFUL for example to mysqld (which is already workarounded) | |
736 | kill -KILL $pid | |
737 | usleep 100000 | |
738 | fi | |
739 | fi | |
740 | checkpid $pid | |
741 | result=$? | |
742 | if [ "$result" -eq 0 ]; then | |
743 | fail | |
744 | log_failed "$1 shutdown" | |
745 | else | |
746 | ok | |
747 | log_success "$1 shutdown" | |
748 | fi | |
749 | result=$(( ! $result )) | |
750 | else | |
751 | # use specified level only | |
752 | if checkpid $pid > /dev/null 2>&1; then | |
753 | kill $killlevel $pid | |
754 | result=$? | |
755 | if [ "$result" -eq 0 ]; then | |
756 | ok | |
757 | log_success "$1 got $killlevel" | |
758 | else | |
759 | result=7 | |
760 | fail | |
761 | log_failed "$1 didn't get $killlevel" | |
762 | fi | |
763 | else | |
764 | result=7 | |
765 | died | |
766 | log_failed "$1 shutdown" | |
767 | fi | |
768 | fi | |
769 | else | |
770 | died | |
771 | log_failed "$1 shutdown" | |
772 | result=7 | |
773 | fi | |
774 | ||
775 | if [ -n "$waitname" -a -n "$waittime" ]; then | |
776 | # Save basename. | |
777 | base=${waitname##*/} | |
778 | # Find pid. | |
779 | pid=$(pidofproc "$waitname" "$pidfile") | |
780 | [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile") | |
781 | i=0 | |
782 | while [ "$i" -lt "$waittime" ]; do | |
783 | i=$(( i + 1 )) | |
784 | checkpid $pid && sleep 1 || break | |
785 | done | |
786 | fi | |
787 | ||
788 | # Remove pid file if any. | |
789 | if [ "$notset" = "1" ]; then | |
790 | rm -f /var/run/${base}.pid | |
791 | fi | |
792 | ||
793 | return $result | |
794 | } | |
795 | ||
796 | # A function to find the pid of a program. | |
797 | pidofproc() { | |
798 | local pid pidfile base=${1##*/} | |
799 | pidfile="$base.pid" | |
800 | [ -n "$2" ] && pidfile="$2" | |
801 | ||
802 | # Test syntax. | |
803 | if [ $# = 0 ]; then | |
804 | msg_usage " pidofproc {program}" | |
805 | return 2 | |
806 | fi | |
807 | ||
808 | # First try pidfile or "/var/run/*.pid" | |
809 | case "$pidfile" in | |
810 | /*)pidfile="${pidfile}";; | |
811 | *) pidfile="/var/run/$pidfile";; | |
812 | esac | |
813 | if [ -f "${pidfile}" ]; then | |
814 | local p pid="" | |
815 | for p in $(< "${pidfile}"); do | |
816 | [ -z "$(echo "$p" | awk '{gsub(/[0-9]/,"");print;}')" ] && pid="$pid $p" | |
817 | done | |
818 | fi | |
819 | ||
820 | # Next try "pidof" | |
821 | [ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1" | |
822 | pid=$(filter_chroot "$pid") | |
823 | echo $pid | |
824 | } | |
825 | ||
826 | # status [--pidfile PIDFILE] {subsys} [{daemon}]" | |
827 | status() { | |
828 | local pid subsys daemon cpuset_msg pidfile | |
829 | if [ "$1" = "--pidfile" -o "$1" = "-p" ]; then | |
830 | pidfile=$2 | |
831 | case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac | |
832 | shift 2 | |
833 | fi | |
834 | ||
835 | subsys=$1 | |
836 | daemon=${2:-$subsys} | |
837 | ||
838 | # Test syntax. | |
839 | if [ $# = 0 ]; then | |
840 | msg_usage " status [--pidfile PIDFILE] {subsys} [{daemon}]" | |
841 | return 2 | |
842 | fi | |
843 | ||
844 | # if pidfile specified, pid must be there | |
845 | if [ "$pidfile" ]; then | |
846 | [ -f "$pidfile" ] && read pid < $pidfile | |
847 | # filter_chroot does not filter out dead pids, so this extra check, see t/status-pidfile.sh | |
848 | if [ ! -d "/proc/$pid" ]; then | |
849 | pid= | |
850 | fi | |
851 | else | |
852 | pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon) | |
853 | fi | |
854 | pid=$(filter_chroot "$pid") | |
855 | ||
856 | if [ "$pid" ]; then | |
857 | cpuset_msg="..." | |
858 | if [ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS"; then | |
859 | if grep -q "$pid" "/dev/cpuset/${SERVICE_CPUSET}/tasks"; then | |
860 | cpuset_msg=$(nls " in cpuset %s..." "$SERVICE_CPUSET") | |
861 | else | |
862 | cpuset_msg=$(nls " outside of configured cpuset %s..." "$SERVICE_CPUSET") | |
863 | fi | |
864 | fi | |
865 | nls "%s (pid %s) is running%s" "$daemon" "$pid" "$cpuset_msg" | |
866 | return 0 | |
867 | fi | |
868 | ||
869 | # Next try "/var/run/*.pid" files; if pidfile is not set | |
870 | local base=${daemon##*/} | |
871 | if [ -z "$pidfile" -a -f /var/run/${base}.pid ]; then | |
872 | read pid < /var/run/${base}.pid | |
873 | pid=$(filter_chroot "$pid") | |
874 | if [ "$pid" ]; then | |
875 | nls "%s dead but pid file (%s) exists" "$subsys" /var/run/${base}.pid | |
876 | return 1 | |
877 | fi | |
878 | fi | |
879 | ||
880 | # See if /var/lock/subsys/$subsys exists | |
881 | if [ -f /var/lock/subsys/$subsys ]; then | |
882 | nls "daemon %s dead but subsys (%s) locked" "$daemon" "$subsys" | |
883 | return 2 | |
884 | fi | |
885 | nls "%s is stopped" "$subsys" | |
886 | return 3 | |
887 | } | |
888 | ||
889 | # Confirm whether we really want to run this service | |
890 | confirm() { | |
891 | local answer | |
892 | nls -n "Start service %s (Y)es/(N)o/(C)ontinue? [Y] " "$1" | |
893 | read answer | |
894 | case $answer in | |
895 | y|Y|t|T|j|J|"") | |
896 | return 0 | |
897 | ;; | |
898 | c|C|k|K|w|W) | |
899 | return 2 | |
900 | ;; | |
901 | n|N) | |
902 | return 1 | |
903 | ;; | |
904 | *) | |
905 | confirm $1 | |
906 | return $? | |
907 | ;; | |
908 | esac | |
909 | } | |
910 | ||
911 | # module is needed (ie. is requested, is available and isn't loaded already) | |
912 | is_module() { | |
913 | # module name without .o at end | |
914 | if ! lsmod | grep -q "$1"; then | |
915 | if ls -R /lib/modules/$(uname -r)/ 2> /dev/null | grep -q "${1}.\(\|k\)o\(\|.gz\)"; then | |
916 | # true | |
917 | return 0 | |
918 | fi | |
919 | fi | |
920 | # false | |
921 | return 1 | |
922 | } | |
923 | ||
924 | _modprobe() { | |
925 | local parsed single die args foo result | |
926 | parsed=no | |
927 | while is_no "$parsed"; do | |
928 | case "$1" in | |
929 | "single") | |
930 | single=yes | |
931 | shift | |
932 | ;; | |
933 | "die") | |
934 | die=yes | |
935 | shift | |
936 | ;; | |
937 | -*) | |
938 | args="$args $1" | |
939 | shift | |
940 | ;; | |
941 | *) | |
942 | parsed=yes | |
943 | ;; | |
944 | esac | |
945 | done | |
946 | if is_yes "${single}"; then | |
947 | foo="$@" | |
948 | show "Loading %s kernel module(s)" "$foo" | |
949 | busy | |
950 | fi | |
951 | if [ -x /sbin/modprobe ]; then | |
952 | /sbin/modprobe -s $args "$@" | |
953 | result=$? | |
954 | else | |
955 | deltext; fail | |
956 | result=1 | |
957 | fi | |
958 | if is_yes "${single}"; then | |
959 | deltext | |
960 | if [ $result = "0" ]; then | |
961 | is_yes "$single" && ok | |
962 | else | |
963 | fail | |
964 | if is_yes "$die"; then | |
965 | nls "Could not load %s kernel module(s)" "$@" | |
966 | exit 1 | |
967 | fi | |
968 | fi | |
969 | fi | |
970 | } | |
971 | ||
972 | if is_no "$RC_LOGGING"; then | |
973 | log_success() { | |
974 | : | |
975 | } | |
976 | ||
977 | log_failed() { | |
978 | : | |
979 | } | |
980 | else | |
981 | log_success() { | |
982 | initlog -n $0 -s "$1 $2" -e 1 | |
983 | } | |
984 | ||
985 | log_failed() { | |
986 | initlog -n $0 -s "$1 $2" -e 2 | |
987 | } | |
988 | fi | |
989 | ||
990 | # Check if any flavor of portmapper is running | |
991 | check_portmapper() { | |
992 | if [ -x /usr/sbin/rpcinfo ]; then | |
993 | if /usr/sbin/rpcinfo -p localhost >/dev/null 2>/dev/null; then | |
994 | return 0 | |
995 | else | |
996 | return 1 | |
997 | fi | |
998 | elif [ -z "$(pidof portmap)" -a -z "$(pidof rpcbind)" ]; then | |
999 | return 1 | |
1000 | fi | |
1001 | return 0 | |
1002 | } | |
1003 | ||
1004 | # is_fsmounted fstype mntpoint | |
1005 | # Check if filesystem fstype is mounted on mntpoint | |
1006 | is_fsmounted() { | |
1007 | local fstype=$1 | |
1008 | local mntpoint=$2 | |
1009 | ||
1010 | [ -n "$fstype" -a -n "$mntpoint" ] || return 1 | |
1011 | ||
1012 | if [ -r /proc/mounts ]; then | |
1013 | grep -qE "[[:blank:]]$mntpoint[[:blank:]]+$fstype[[:blank:]]" /proc/mounts | |
1014 | return $? | |
1015 | else | |
1016 | if [ "$(stat -L -f -c %T $mntpoint 2>/dev/null)" = "$fstype" ]; then | |
1017 | return 0 | |
1018 | else | |
1019 | return 1 | |
1020 | fi | |
1021 | fi | |
1022 | } | |
1023 | ||
1024 | rc_cache_init() { | |
1025 | # If we have cachefile, use it. | |
1026 | # If we don't, create memory variables and try to save silently, | |
1027 | local cachefile='/var/cache/rc-scripts/msg.cache' | |
1028 | ||
1029 | local term | |
1030 | if is_yes "$ISATTY"; then | |
1031 | term=$TERM | |
1032 | else | |
1033 | term=dumb | |
1034 | fi | |
1035 | ||
1036 | # We create $check variable which is used to invalidate the cache. | |
1037 | # The $check contains user locale and terminal. | |
1038 | local check="$term.$LC_MESSAGES.$INIT_COL" | |
1039 | ||
1040 | if [ -f "$cachefile" -a "$cachefile" -nt /etc/sysconfig/system -a "$cachefile" -nt /etc/sysconfig/init-colors ]; then | |
1041 | if . "$cachefile" 2>/dev/null; then | |
1042 | if [ "$check" = "$_check" ]; then | |
1043 | return | |
1044 | fi | |
1045 | fi | |
1046 | fi | |
1047 | ||
1048 | # primitive caching | |
1049 | _busy=$(progress "BUSY" "$CBUSY") | |
1050 | _ok=$(progress "DONE") | |
1051 | _started=$(progress "WORK") | |
1052 | _fail=$(progress "FAIL" "$CFAIL") | |
1053 | _died=$(progress "DIED" "$CFAIL") | |
1054 | ||
1055 | # we don't use heredoc, as ksh attempts to create tempfile then | |
1056 | (> "$cachefile" ) 2>/dev/null || return | |
1057 | echo "_busy='$_busy';" >> "$cachefile" | |
1058 | echo "_ok='$_ok';" >> "$cachefile" | |
1059 | echo "_started='$_started';" >> "$cachefile" | |
1060 | echo "_fail='$_fail';" >> "$cachefile" | |
1061 | echo "_died='$_died';" >> "$cachefile" | |
1062 | echo "_check='$check';" >> "$cachefile" | |
1063 | } | |
1064 | ||
1065 | rc_gettext_init() { | |
1066 | if [ -z "$GETTEXT" ]; then | |
1067 | if [ -x /bin/gettext -o -x /usr/bin/gettext ]; then | |
1068 | GETTEXT=yes | |
1069 | else | |
1070 | GETTEXT=no | |
1071 | fi | |
1072 | fi | |
1073 | ||
1074 | if [ -z "$TPUT" ]; then | |
1075 | if [ -d /usr/share/terminfo ] && [ -x /usr/bin/tput -o -x /bin/tput ]; then | |
1076 | TPUT=yes | |
1077 | # check if we are on proper terminal | |
1078 | tput longname >/dev/null 2>&1 || TPUT=no | |
1079 | else | |
1080 | TPUT=no | |
1081 | fi | |
1082 | fi | |
1083 | } | |
1084 | ||
1085 | use_upstart () { | |
1086 | # True when upstart-event-based boot should be used | |
1087 | is_yes "$USE_UPSTART" && return 0 | |
1088 | is_no "$USE_UPSTART" && return 1 | |
1089 | if [ ! -x /sbin/initctl ] ; then | |
1090 | USE_UPSTART="no" | |
1091 | return 1 | |
1092 | fi | |
1093 | local cmdline=$(cat /proc/cmdline 2>/dev/null) | |
1094 | if strstr "$cmdline" "pld.no-upstart" ; then | |
1095 | USE_UPSTART="no" | |
1096 | return 1 | |
1097 | else | |
1098 | USE_UPSTART="yes" | |
1099 | return 0 | |
1100 | fi | |
1101 | } | |
1102 | ||
1103 | emit () { | |
1104 | # emit upstart signal | |
1105 | # only when 'upstart' boot is enabled | |
1106 | use_upstart || return 0 | |
1107 | /sbin/initctl emit "$@" | |
1108 | } | |
1109 | ||
1110 | is_upstart_task() { | |
1111 | # Return 0 if the given service is an upstart task. | |
1112 | grep -q '^task' "/etc/init/$1.conf" | |
1113 | } | |
1114 | is_upstart_running() { | |
1115 | # Return 0 if the given service is running via upstart | |
1116 | initctl status "$1" 2>/dev/null | grep -q running | |
1117 | } | |
1118 | upstart_start() { | |
1119 | local service=$1 | |
1120 | is_upstart_running "${service}" && return 0 | |
1121 | msg_starting "${service}" | |
1122 | if errors=$(/sbin/initctl start ${service} 2>&1) ; then | |
1123 | ok | |
1124 | return 0 | |
1125 | else | |
1126 | fail | |
1127 | echo "$errors" >&2 | |
1128 | return 1 | |
1129 | fi | |
1130 | } | |
1131 | upstart_stop() { | |
1132 | local service=$1 | |
1133 | if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then | |
1134 | return 0 | |
1135 | fi | |
1136 | msg_stopping "${service}" | |
1137 | if errors=$(/sbin/initctl stop ${service}) ; then | |
1138 | ok | |
1139 | return 0 | |
1140 | else | |
1141 | fail | |
1142 | echo "$errors" >&2 | |
1143 | return 1 | |
1144 | fi | |
1145 | } | |
1146 | upstart_reload() { | |
1147 | local service=$1 | |
1148 | if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then | |
1149 | return 0 | |
1150 | fi | |
1151 | msg_reloading "${service}" | |
1152 | if errors=$(/sbin/initctl reload ${service}) ; then | |
1153 | ok | |
1154 | return 0 | |
1155 | else | |
1156 | fail | |
1157 | echo "$errors" >&2 | |
1158 | return 1 | |
1159 | fi | |
1160 | } | |
1161 | upstart_status() { | |
1162 | # get service status | |
1163 | # should be compliant with | |
1164 | # http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html | |
1165 | local service=$1 | |
1166 | local status | |
1167 | if is_upstart_task "${service}" ; then | |
1168 | # we probably should have a way to handle task status | |
1169 | return 0 | |
1170 | fi | |
1171 | if ! status=$(/sbin/initctl status "${service}") ; then | |
1172 | # program or service status is not known | |
1173 | return 4 | |
1174 | fi | |
1175 | if strstr "$status" "running" ; then | |
1176 | # program is running or service is OK | |
1177 | echo "$status" | |
1178 | return 0 | |
1179 | else | |
1180 | # program is not running | |
1181 | echo "$status" | |
1182 | return 3 | |
1183 | fi | |
1184 | # TODO: other statuses | |
1185 | } | |
1186 | ||
1187 | _upstart_controlled () { | |
1188 | # If the service is to be handled by upstart | |
1189 | # execute the start/stop/etc. commands the upstart way | |
1190 | if ! use_upstart ; then | |
1191 | return 0 | |
1192 | fi | |
1193 | local script=$1 | |
1194 | shift | |
1195 | local command=$1 | |
1196 | shift | |
1197 | local name=$(basename "$script") | |
1198 | if [ ! -f /etc/init/${name}.conf ] ; then | |
1199 | return 0 | |
1200 | fi | |
1201 | local commands | |
1202 | local extra_commands | |
1203 | local has_configtest | |
1204 | if [ "$1" = "--except" ] ; then | |
1205 | shift | |
1206 | commands="$*" | |
1207 | for cmd in $commands ; do | |
1208 | if [ "$command" = "$cmd" ] ; then | |
1209 | return 0 | |
1210 | fi | |
1211 | case "$cmd" in | |
1212 | start|stop|status|reload|restart|try-restart|force-reload) | |
1213 | ;; | |
1214 | configtest) | |
1215 | has_configtest=yes | |
1216 | extra_commands="|$cmd" | |
1217 | ;; | |
1218 | *) | |
1219 | extra_commands="|$cmd" | |
1220 | ;; | |
1221 | esac | |
1222 | done | |
1223 | elif [ -n "$*" ] ; then | |
1224 | commands="$*" | |
1225 | local cmd | |
1226 | local found=0 | |
1227 | # is there a better way | |
1228 | for cmd in $commands ; do | |
1229 | if [ "$command" = "$cmd" ] ; then | |
1230 | found=1 | |
1231 | break; | |
1232 | fi | |
1233 | done | |
1234 | if [ $found = 0 ] ; then | |
1235 | # let the script handle it | |
1236 | return 0 | |
1237 | fi | |
1238 | fi | |
1239 | case "$command" in | |
1240 | start) | |
1241 | upstart_start $name | |
1242 | exit $? | |
1243 | ;; | |
1244 | stop) | |
1245 | upstart_stop $name | |
1246 | exit $? | |
1247 | ;; | |
1248 | status) | |
1249 | upstart_status $name | |
1250 | exit $? | |
1251 | ;; | |
1252 | restart) | |
1253 | if is_yes "$has_configtest" ; then | |
1254 | "$script" configtest || exit 1 | |
1255 | fi | |
1256 | upstart_stop $name | |
1257 | upstart_start $name | |
1258 | exit $? | |
1259 | ;; | |
1260 | try-restart) | |
1261 | if ! is_upstart_running "$name" ; then | |
1262 | exit 0 | |
1263 | fi | |
1264 | if is_yes "$has_configtest" ; then | |
1265 | "$script" configtest || exit 1 | |
1266 | fi | |
1267 | upstart_stop $name | |
1268 | upstart_start $name | |
1269 | exit $? | |
1270 | ;; | |
1271 | reload) | |
1272 | if is_yes "$has_configtest" ; then | |
1273 | "$script" configtest || exit 1 | |
1274 | fi | |
1275 | if is_upstart_task "$name" ; then | |
1276 | nls "$command not implemented for $name" | |
1277 | exit 3 | |
1278 | else | |
1279 | upstart_reload "$name" | |
1280 | exit $? | |
1281 | fi | |
1282 | ;; | |
1283 | force-reload) | |
1284 | if is_yes "$has_configtest" ; then | |
1285 | "$script" configtest || exit 1 | |
1286 | fi | |
1287 | if is_upstart_task "$name" ; then | |
1288 | upstart_stop "$name" | |
1289 | upstart_start "$name" | |
1290 | exit $? | |
1291 | else | |
1292 | upstart_reload "$name" | |
1293 | exit $? | |
1294 | fi | |
1295 | ;; | |
1296 | *) | |
1297 | msg_usage "$0 {start|stop|restart|reload|force-reload|status$extra_commands}" | |
1298 | exit 3 | |
1299 | ;; | |
1300 | esac | |
1301 | return 1 # should not happen | |
1302 | } | |
1303 | ||
1304 | # Usage: | |
1305 | # somewhere at the begining of init script: | |
1306 | # upstart_controlled | |
1307 | # - to pass implement all upstart commands via initctl | |
1308 | # start, stop, status, restart, reload and force_reload | |
1309 | # are implemented | |
1310 | # upstart_controlled command... | |
1311 | # - to pass handle only specific commands the upstart way | |
1312 | # and leave the rest to the script | |
1313 | # | |
1314 | alias upstart_controlled='_upstart_controlled $0 "$@"' | |
1315 | ||
1316 | rc_gettext_init | |
1317 | rc_cache_init | |
1318 | ||
1319 | #/* | |
1320 | # * Local variables: | |
1321 | # * mode: sh | |
1322 | # * indent-tabs-mode: notnil | |
1323 | # * End: | |
1324 | # * | |
1325 | # */ |