source: bootscripts/lfs/lib/services/init-functions

trunk
Last change on this file was b3daf01, checked in by Pierre Labastie <pierre.labastie@…>, 19 months ago

Typos reported by "rhubarbpieguy"

  • Property mode set to 100644
File size: 29.0 KB
Line 
1#!/bin/sh
2########################################################################
3#
4# Begin /lib/lsb/init-funtions
5#
6# Description : Run Level Control Functions
7#
8# Authors : Gerard Beekmans - gerard@linuxfromscratch.org
9# : DJ Lucas - dj@linuxfromscratch.org
10# Update : Bruce Dubbs - bdubbs@linuxfromscratch.org
11#
12# Version : LFS 7.0
13#
14# Notes : With code based on Matthias Benkmann's simpleinit-msb
15# http://winterdrache.de/linux/newboot/index.html
16#
17# The file should be located in /lib/lsb
18#
19########################################################################
20
21## Environmental setup
22# Setup default values for environment
23umask 022
24export PATH="/bin:/usr/bin:/sbin:/usr/sbin"
25
26## Set color commands, used via echo
27# Please consult `man console_codes for more information
28# under the "ECMA-48 Set Graphics Rendition" section
29#
30# Warning: when switching from a 8bit to a 9bit font,
31# the linux console will reinterpret the bold (1;) to
32# the top 256 glyphs of the 9bit font. This does
33# not affect framebuffer consoles
34
35NORMAL="\\033[0;39m" # Standard console grey
36SUCCESS="\\033[1;32m" # Success is green
37WARNING="\\033[1;33m" # Warnings are yellow
38FAILURE="\\033[1;31m" # Failures are red
39INFO="\\033[1;36m" # Information is light cyan
40BRACKET="\\033[1;34m" # Brackets are blue
41
42# Use a colored prefix
43BMPREFIX=" "
44SUCCESS_PREFIX="${SUCCESS} * ${NORMAL} "
45FAILURE_PREFIX="${FAILURE}*****${NORMAL} "
46WARNING_PREFIX="${WARNING} *** ${NORMAL} "
47SKIP_PREFIX="${INFO} S ${NORMAL}"
48
49SUCCESS_SUFFIX="${BRACKET}[${SUCCESS} OK ${BRACKET}]${NORMAL}"
50FAILURE_SUFFIX="${BRACKET}[${FAILURE} FAIL ${BRACKET}]${NORMAL}"
51WARNING_SUFFIX="${BRACKET}[${WARNING} WARN ${BRACKET}]${NORMAL}"
52SKIP_SUFFIX="${BRACKET}[${INFO} SKIP ${BRACKET}]${NORMAL}"
53
54BOOTLOG=/run/bootlog
55KILLDELAY=3
56SCRIPT_STAT="0"
57
58# Set any user specified environment variables e.g. HEADLESS
59[ -r /etc/sysconfig/rc.site ] && . /etc/sysconfig/rc.site
60
61## Screen Dimensions
62# Find current screen size
63if [ -z "${COLUMNS}" ]; then
64 COLUMNS=$(stty size)
65 COLUMNS=${COLUMNS##* }
66fi
67
68# When using remote connections, such as a serial port, stty size returns 0
69if [ "${COLUMNS}" = "0" ]; then
70 COLUMNS=80
71fi
72
73## Measurements for positioning result messages
74COL=$((${COLUMNS} - 8))
75WCOL=$((${COL} - 2))
76
77## Set Cursor Position Commands, used via echo
78SET_COL="\\033[${COL}G" # at the $COL char
79SET_WCOL="\\033[${WCOL}G" # at the $WCOL char
80CURS_UP="\\033[1A\\033[0G" # Up one line, at the 0'th char
81CURS_ZERO="\\033[0G"
82
83################################################################################
84# start_daemon() #
85# Usage: start_daemon [-f] [-n nicelevel] [-p pidfile] pathname [args...] #
86# #
87# Purpose: This runs the specified program as a daemon #
88# #
89# Inputs: -f: (force) run the program even if it is already running. #
90# -n nicelevel: specify a nice level. See 'man nice(1)'. #
91# -p pidfile: use the specified file to determine PIDs. #
92# pathname: the complete path to the specified program #
93# args: additional arguments passed to the program (pathname) #
94# #
95# Return values (as defined by LSB exit codes): #
96# 0 - program is running or service is OK #
97# 1 - generic or unspecified error #
98# 2 - invalid or excessive argument(s) #
99# 5 - program is not installed #
100################################################################################
101start_daemon()
102{
103 local force=""
104 local nice="0"
105 local pidfile=""
106 local pidlist=""
107 local retval=""
108
109 # Process arguments
110 while true
111 do
112 case "${1}" in
113
114 -f)
115 force="1"
116 shift 1
117 ;;
118
119 -n)
120 nice="${2}"
121 shift 2
122 ;;
123
124 -p)
125 pidfile="${2}"
126 shift 2
127 ;;
128
129 -*)
130 return 2
131 ;;
132
133 *)
134 program="${1}"
135 break
136 ;;
137 esac
138 done
139
140 # Check for a valid program
141 if [ ! -e "${program}" ]; then return 5; fi
142
143 # Execute
144 if [ -z "${force}" ]; then
145 if [ -z "${pidfile}" ]; then
146 # Determine the pid by discovery
147 pidlist=`pidofproc "${1}"`
148 retval="${?}"
149 else
150 # The PID file contains the needed PIDs
151 # Note that by LSB requirement, the path must be given to pidofproc,
152 # however, it is not used by the current implementation or standard.
153 pidlist=`pidofproc -p "${pidfile}" "${1}"`
154 retval="${?}"
155 fi
156
157 # Return a value ONLY
158 # It is the init script's (or distribution's functions) responsibility
159 # to log messages!
160 case "${retval}" in
161
162 0)
163 # Program is already running correctly, this is a
164 # successful start.
165 return 0
166 ;;
167
168 1)
169 # Program is not running, but an invalid pid file exists
170 # remove the pid file and continue
171 rm -f "${pidfile}"
172 ;;
173
174 3)
175 # Program is not running and no pidfile exists
176 # do nothing here, let start_deamon continue.
177 ;;
178
179 *)
180 # Others as returned by status values shall not be interpreted
181 # and returned as an unspecified error.
182 return 1
183 ;;
184 esac
185 fi
186
187 # Do the start!
188 nice -n "${nice}" "${@}"
189}
190
191################################################################################
192# killproc() #
193# Usage: killproc [-p pidfile] pathname [signal] #
194# #
195# Purpose: Send control signals to running processes #
196# #
197# Inputs: -p pidfile, uses the specified pidfile #
198# pathname, pathname to the specified program #
199# signal, send this signal to pathname #
200# #
201# Return values (as defined by LSB exit codes): #
202# 0 - program (pathname) has stopped/is already stopped or a #
203# running program has been sent specified signal and stopped #
204# successfully #
205# 1 - generic or unspecified error #
206# 2 - invalid or excessive argument(s) #
207# 5 - program is not installed #
208# 7 - program is not running and a signal was supplied #
209################################################################################
210killproc()
211{
212 local pidfile
213 local program
214 local prefix
215 local progname
216 local signal="-TERM"
217 local fallback="-KILL"
218 local nosig
219 local pidlist
220 local retval
221 local pid
222 local delay="30"
223 local piddead
224 local dtime
225
226 # Process arguments
227 while true; do
228 case "${1}" in
229 -p)
230 pidfile="${2}"
231 shift 2
232 ;;
233
234 *)
235 program="${1}"
236 if [ -n "${2}" ]; then
237 signal="${2}"
238 fallback=""
239 else
240 nosig=1
241 fi
242
243 # Error on additional arguments
244 if [ -n "${3}" ]; then
245 return 2
246 else
247 break
248 fi
249 ;;
250 esac
251 done
252
253 # Check for a valid program
254 if [ ! -e "${program}" ]; then return 5; fi
255
256 # Check for a valid signal
257 check_signal "${signal}"
258 if [ "${?}" -ne "0" ]; then return 2; fi
259
260 # Get a list of pids
261 if [ -z "${pidfile}" ]; then
262 # determine the pid by discovery
263 pidlist=`pidofproc "${1}"`
264 retval="${?}"
265 else
266 # The PID file contains the needed PIDs
267 # Note that by LSB requirement, the path must be given to pidofproc,
268 # however, it is not used by the current implementation or standard.
269 pidlist=`pidofproc -p "${pidfile}" "${1}"`
270 retval="${?}"
271 fi
272
273 # Return a value ONLY
274 # It is the init script's (or distribution's functions) responsibility
275 # to log messages!
276 case "${retval}" in
277
278 0)
279 # Program is running correctly
280 # Do nothing here, let killproc continue.
281 ;;
282
283 1)
284 # Program is not running, but an invalid pid file exists
285 # Remove the pid file.
286
287 progname=${program##*/}
288
289 if [[ -e "/run/${progname}.pid" ]]; then
290 pidfile="/run/${progname}.pid"
291 rm -f "${pidfile}"
292 fi
293
294 # This is only a success if no signal was passed.
295 if [ -n "${nosig}" ]; then
296 return 0
297 else
298 return 7
299 fi
300 ;;
301
302 3)
303 # Program is not running and no pidfile exists
304 # This is only a success if no signal was passed.
305 if [ -n "${nosig}" ]; then
306 return 0
307 else
308 return 7
309 fi
310 ;;
311
312 *)
313 # Others as returned by status values shall not be interpreted
314 # and returned as an unspecified error.
315 return 1
316 ;;
317 esac
318
319 # Perform different actions for exit signals and control signals
320 check_sig_type "${signal}"
321
322 if [ "${?}" -eq "0" ]; then # Signal is used to terminate the program
323
324 # Account for empty pidlist (pid file still exists and no
325 # signal was given)
326 if [ "${pidlist}" != "" ]; then
327
328 # Kill the list of pids
329 for pid in ${pidlist}; do
330
331 kill -0 "${pid}" 2> /dev/null
332
333 if [ "${?}" -ne "0" ]; then
334 # Process is dead, continue to next and assume all is well
335 continue
336 else
337 kill "${signal}" "${pid}" 2> /dev/null
338
339 # Wait up to ${delay}/10 seconds to for "${pid}" to
340 # terminate in 10ths of a second
341
342 while [ "${delay}" -ne "0" ]; do
343 kill -0 "${pid}" 2> /dev/null || piddead="1"
344 if [ "${piddead}" = "1" ]; then break; fi
345 sleep 0.1
346 delay="$(( ${delay} - 1 ))"
347 done
348
349 # If a fallback is set, and program is still running, then
350 # use the fallback
351 if [ -n "${fallback}" -a "${piddead}" != "1" ]; then
352 kill "${fallback}" "${pid}" 2> /dev/null
353 sleep 1
354 # Check again, and fail if still running
355 kill -0 "${pid}" 2> /dev/null && return 1
356 fi
357 fi
358 done
359 fi
360
361 # Check for and remove stale PID files.
362 if [ -z "${pidfile}" ]; then
363 # Find the basename of $program
364 prefix=`echo "${program}" | sed 's/[^/]*$//'`
365 progname=`echo "${program}" | sed "s@${prefix}@@"`
366
367 if [ -e "/run/${progname}.pid" ]; then
368 rm -f "/run/${progname}.pid" 2> /dev/null
369 fi
370 else
371 if [ -e "${pidfile}" ]; then rm -f "${pidfile}" 2> /dev/null; fi
372 fi
373
374 # For signals that do not expect a program to exit, simply
375 # let kill do its job, and evaluate kill's return for value
376
377 else # check_sig_type - signal is not used to terminate program
378 for pid in ${pidlist}; do
379 kill "${signal}" "${pid}"
380 if [ "${?}" -ne "0" ]; then return 1; fi
381 done
382 fi
383}
384
385################################################################################
386# pidofproc() #
387# Usage: pidofproc [-p pidfile] pathname #
388# #
389# Purpose: This function returns one or more pid(s) for a particular daemon #
390# #
391# Inputs: -p pidfile, use the specified pidfile instead of pidof #
392# pathname, path to the specified program #
393# #
394# Return values (as defined by LSB status codes): #
395# 0 - Success (PIDs to stdout) #
396# 1 - Program is dead, PID file still exists (remaining PIDs output) #
397# 3 - Program is not running (no output) #
398################################################################################
399pidofproc()
400{
401 local pidfile
402 local program
403 local prefix
404 local progname
405 local pidlist
406 local lpids
407 local exitstatus="0"
408
409 # Process arguments
410 while true; do
411 case "${1}" in
412
413 -p)
414 pidfile="${2}"
415 shift 2
416 ;;
417
418 *)
419 program="${1}"
420 if [ -n "${2}" ]; then
421 # Too many arguments
422 # Since this is status, return unknown
423 return 4
424 else
425 break
426 fi
427 ;;
428 esac
429 done
430
431 # If a PID file is not specified, try and find one.
432 if [ -z "${pidfile}" ]; then
433 # Get the program's basename
434 prefix=`echo "${program}" | sed 's/[^/]*$//'`
435
436 if [ -z "${prefix}" ]; then
437 progname="${program}"
438 else
439 progname=`echo "${program}" | sed "s@${prefix}@@"`
440 fi
441
442 # If a PID file exists with that name, assume that is it.
443 if [ -e "/run/${progname}.pid" ]; then
444 pidfile="/run/${progname}.pid"
445 fi
446 fi
447
448 # If a PID file is set and exists, use it.
449 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
450
451 # Use the value in the first line of the pidfile
452 pidlist=`/bin/head -n1 "${pidfile}"`
453 # This can optionally be written as 'sed 1q' to repalce 'head -n1'
454 # should LFS move /bin/head to /usr/bin/head
455 else
456 # Use pidof
457 pidlist=`pidof "${program}"`
458 fi
459
460 # Figure out if all listed PIDs are running.
461 for pid in ${pidlist}; do
462 kill -0 ${pid} 2> /dev/null
463
464 if [ "${?}" -eq "0" ]; then
465 lpids="${lpids}${pid} "
466 else
467 exitstatus="1"
468 fi
469 done
470
471 if [ -z "${lpids}" -a ! -f "${pidfile}" ]; then
472 return 3
473 else
474 echo "${lpids}"
475 return "${exitstatus}"
476 fi
477}
478
479################################################################################
480# statusproc() #
481# Usage: statusproc [-p pidfile] pathname #
482# #
483# Purpose: This function prints the status of a particular daemon to stdout #
484# #
485# Inputs: -p pidfile, use the specified pidfile instead of pidof #
486# pathname, path to the specified program #
487# #
488# Return values: #
489# 0 - Status printed #
490# 1 - Input error. The daemon to check was not specified. #
491################################################################################
492statusproc()
493{
494 local pidfile
495 local pidlist
496
497 if [ "${#}" = "0" ]; then
498 echo "Usage: statusproc [-p pidfle] {program}"
499 exit 1
500 fi
501
502 # Process arguments
503 while true; do
504 case "${1}" in
505
506 -p)
507 pidfile="${2}"
508 shift 2
509 ;;
510
511 *)
512 if [ -n "${2}" ]; then
513 echo "Too many arguments"
514 return 1
515 else
516 break
517 fi
518 ;;
519 esac
520 done
521
522 if [ -n "${pidfile}" ]; then
523 pidlist=`pidofproc -p "${pidfile}" $@`
524 else
525 pidlist=`pidofproc $@`
526 fi
527
528 # Trim trailing blanks
529 pidlist=`echo "${pidlist}" | sed -r 's/ +$//'`
530
531 base="${1##*/}"
532
533 if [ -n "${pidlist}" ]; then
534 /bin/echo -e "${INFO}${base} is running with Process" \
535 "ID(s) ${pidlist}.${NORMAL}"
536 else
537 if [ -n "${base}" -a -e "/run/${base}.pid" ]; then
538 /bin/echo -e "${WARNING}${1} is not running but" \
539 "/run/${base}.pid exists.${NORMAL}"
540 else
541 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
542 /bin/echo -e "${WARNING}${1} is not running" \
543 "but ${pidfile} exists.${NORMAL}"
544 else
545 /bin/echo -e "${INFO}${1} is not running.${NORMAL}"
546 fi
547 fi
548 fi
549}
550
551################################################################################
552# timespec() #
553# #
554# Purpose: An internal utility function to format a timestamp #
555# a boot log file. Sets the STAMP variable. #
556# #
557# Return value: Not used #
558################################################################################
559timespec()
560{
561 STAMP="$(echo `date +"%b %d %T %:z"` `hostname`) "
562 return 0
563}
564
565################################################################################
566# log_success_msg() #
567# Usage: log_success_msg ["message"] #
568# #
569# Purpose: Print a successful status message to the screen and #
570# a boot log file. #
571# #
572# Inputs: $@ - Message #
573# #
574# Return values: Not used #
575################################################################################
576log_success_msg()
577{
578 /bin/echo -n -e "${BMPREFIX}${@}"
579 /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}"
580
581 # Strip non-printable characters from log file
582 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
583
584 timespec
585 /bin/echo -e "${STAMP} ${logmessage} OK" >> ${BOOTLOG}
586
587 return 0
588}
589
590log_success_msg2()
591{
592 /bin/echo -n -e "${BMPREFIX}${@}"
593 /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}"
594
595 echo " OK" >> ${BOOTLOG}
596
597 return 0
598}
599
600################################################################################
601# log_failure_msg() #
602# Usage: log_failure_msg ["message"] #
603# #
604# Purpose: Print a failure status message to the screen and #
605# a boot log file. #
606# #
607# Inputs: $@ - Message #
608# #
609# Return values: Not used #
610################################################################################
611log_failure_msg()
612{
613 /bin/echo -n -e "${BMPREFIX}${@}"
614 /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}"
615
616 # Strip non-printable characters from log file
617
618 timespec
619 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
620 /bin/echo -e "${STAMP} ${logmessage} FAIL" >> ${BOOTLOG}
621
622 return 0
623}
624
625log_failure_msg2()
626{
627 /bin/echo -n -e "${BMPREFIX}${@}"
628 /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}"
629
630 echo "FAIL" >> ${BOOTLOG}
631
632 return 0
633}
634
635################################################################################
636# log_warning_msg() #
637# Usage: log_warning_msg ["message"] #
638# #
639# Purpose: Print a warning status message to the screen and #
640# a boot log file. #
641# #
642# Return values: Not used #
643################################################################################
644log_warning_msg()
645{
646 /bin/echo -n -e "${BMPREFIX}${@}"
647 /bin/echo -e "${CURS_ZERO}${WARNING_PREFIX}${SET_COL}${WARNING_SUFFIX}"
648
649 # Strip non-printable characters from log file
650 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
651 timespec
652 /bin/echo -e "${STAMP} ${logmessage} WARN" >> ${BOOTLOG}
653
654 return 0
655}
656
657log_skip_msg()
658{
659 /bin/echo -n -e "${BMPREFIX}${@}"
660 /bin/echo -e "${CURS_ZERO}${SKIP_PREFIX}${SET_COL}${SKIP_SUFFIX}"
661
662 # Strip non-printable characters from log file
663 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
664 /bin/echo "SKIP" >> ${BOOTLOG}
665
666 return 0
667}
668
669################################################################################
670# log_info_msg() #
671# Usage: log_info_msg message #
672# #
673# Purpose: Print an information message to the screen and #
674# a boot log file. Does not print a trailing newline character. #
675# #
676# Return values: Not used #
677################################################################################
678log_info_msg()
679{
680 /bin/echo -n -e "${BMPREFIX}${@}"
681
682 # Strip non-printable characters from log file
683 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
684 timespec
685 /bin/echo -n -e "${STAMP} ${logmessage}" >> ${BOOTLOG}
686
687 return 0
688}
689
690log_info_msg2()
691{
692 /bin/echo -n -e "${@}"
693
694 # Strip non-printable characters from log file
695 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
696 /bin/echo -n -e "${logmessage}" >> ${BOOTLOG}
697
698 return 0
699}
700
701################################################################################
702# evaluate_retval() #
703# Usage: Evaluate a return value and print success or failure as appropriate #
704# #
705# Purpose: Convenience function to terminate an info message #
706# #
707# Return values: Not used #
708################################################################################
709evaluate_retval()
710{
711 local error_value="${?}"
712
713 if [ ${error_value} = 0 ]; then
714 log_success_msg2
715 else
716 log_failure_msg2
717 fi
718}
719
720################################################################################
721# check_signal() #
722# Usage: check_signal [ -{signal} ] #
723# #
724# Purpose: Check for a valid signal. This is not defined by any LSB draft, #
725# however, it is required to check the signals to determine if the #
726# signals chosen are invalid arguments to the other functions. #
727# #
728# Inputs: Accepts a single string value in the form of -{signal} #
729# #
730# Return values: #
731# 0 - Success (signal is valid #
732# 1 - Signal is not valid #
733################################################################################
734check_signal()
735{
736 local valsig
737
738 # Add error handling for invalid signals
739 valsig=" -ALRM -HUP -INT -KILL -PIPE -POLL -PROF -TERM -USR1 -USR2"
740 valsig="${valsig} -VTALRM -STKFLT -PWR -WINCH -CHLD -URG -TSTP -TTIN"
741 valsig="${valsig} -TTOU -STOP -CONT -ABRT -FPE -ILL -QUIT -SEGV -TRAP"
742 valsig="${valsig} -SYS -EMT -BUS -XCPU -XFSZ -0 -1 -2 -3 -4 -5 -6 -8 -9"
743 valsig="${valsig} -11 -13 -14 -15 "
744
745 echo "${valsig}" | grep -- " ${1} " > /dev/null
746
747 if [ "${?}" -eq "0" ]; then
748 return 0
749 else
750 return 1
751 fi
752}
753
754################################################################################
755# check_sig_type() #
756# Usage: check_signal [ -{signal} | {signal} ] #
757# #
758# Purpose: Check if signal is a program termination signal or a control signal #
759# This is not defined by any LSB draft, however, it is required to #
760# check the signals to determine if they are intended to end a #
761# program or simply to control it. #
762# #
763# Inputs: Accepts a single string value in the form or -{signal} or {signal} #
764# #
765# Return values: #
766# 0 - Signal is used for program termination #
767# 1 - Signal is used for program control #
768################################################################################
769check_sig_type()
770{
771 local valsig
772
773 # The list of termination signals (limited to generally used items)
774 valsig=" -ALRM -INT -KILL -TERM -PWR -STOP -ABRT -QUIT -2 -3 -6 -9 -14 -15 "
775
776 echo "${valsig}" | grep -- " ${1} " > /dev/null
777
778 if [ "${?}" -eq "0" ]; then
779 return 0
780 else
781 return 1
782 fi
783}
784
785################################################################################
786# wait_for_user() #
787# #
788# Purpose: Wait for the user to respond if not a headless system #
789# #
790################################################################################
791wait_for_user()
792{
793 # Wait for the user by default
794 [ "${HEADLESS=0}" = "0" ] && read ENTER
795 return 0
796}
797
798################################################################################
799# is_true() #
800# #
801# Purpose: Utility to test if a variable is true | yes | 1 #
802# #
803################################################################################
804is_true()
805{
806 [ "$1" = "1" ] || [ "$1" = "yes" ] || [ "$1" = "true" ] || [ "$1" = "y" ] ||
807 [ "$1" = "t" ]
808}
809
810# End /lib/lsb/init-functions
Note: See TracBrowser for help on using the repository browser.