source: bootscripts/lfs/lib/services/init-functions@ 5e06d04

multilib-10.1
Last change on this file since 5e06d04 was 5e06d04, checked in by Thomas Trepl <thomas@…>, 3 years ago

Merge changes from trunk to multilib

git-svn-id: http://svn.linuxfromscratch.org/LFS/branches/multilib@12107 4aa44e1e-78dd-0310-a6d2-fbcd4c07a689

  • Property mode set to 100644
File size: 28.9 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) responsibilty
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) responsibilty
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 rm -f "${pidfile}"
287
288 # This is only a success if no signal was passed.
289 if [ -n "${nosig}" ]; then
290 return 0
291 else
292 return 7
293 fi
294 ;;
295
296 3)
297 # Program is not running and no pidfile exists
298 # This is only a success if no signal was passed.
299 if [ -n "${nosig}" ]; then
300 return 0
301 else
302 return 7
303 fi
304 ;;
305
306 *)
307 # Others as returned by status values shall not be interpreted
308 # and returned as an unspecified error.
309 return 1
310 ;;
311 esac
312
313 # Perform different actions for exit signals and control signals
314 check_sig_type "${signal}"
315
316 if [ "${?}" -eq "0" ]; then # Signal is used to terminate the program
317
318 # Account for empty pidlist (pid file still exists and no
319 # signal was given)
320 if [ "${pidlist}" != "" ]; then
321
322 # Kill the list of pids
323 for pid in ${pidlist}; do
324
325 kill -0 "${pid}" 2> /dev/null
326
327 if [ "${?}" -ne "0" ]; then
328 # Process is dead, continue to next and assume all is well
329 continue
330 else
331 kill "${signal}" "${pid}" 2> /dev/null
332
333 # Wait up to ${delay}/10 seconds to for "${pid}" to
334 # terminate in 10ths of a second
335
336 while [ "${delay}" -ne "0" ]; do
337 kill -0 "${pid}" 2> /dev/null || piddead="1"
338 if [ "${piddead}" = "1" ]; then break; fi
339 sleep 0.1
340 delay="$(( ${delay} - 1 ))"
341 done
342
343 # If a fallback is set, and program is still running, then
344 # use the fallback
345 if [ -n "${fallback}" -a "${piddead}" != "1" ]; then
346 kill "${fallback}" "${pid}" 2> /dev/null
347 sleep 1
348 # Check again, and fail if still running
349 kill -0 "${pid}" 2> /dev/null && return 1
350 fi
351 fi
352 done
353 fi
354
355 # Check for and remove stale PID files.
356 if [ -z "${pidfile}" ]; then
357 # Find the basename of $program
358 prefix=`echo "${program}" | sed 's/[^/]*$//'`
359 progname=`echo "${program}" | sed "s@${prefix}@@"`
360
361 if [ -e "/run/${progname}.pid" ]; then
362 rm -f "/run/${progname}.pid" 2> /dev/null
363 fi
364 else
365 if [ -e "${pidfile}" ]; then rm -f "${pidfile}" 2> /dev/null; fi
366 fi
367
368 # For signals that do not expect a program to exit, simply
369 # let kill do its job, and evaluate kill's return for value
370
371 else # check_sig_type - signal is not used to terminate program
372 for pid in ${pidlist}; do
373 kill "${signal}" "${pid}"
374 if [ "${?}" -ne "0" ]; then return 1; fi
375 done
376 fi
377}
378
379################################################################################
380# pidofproc() #
381# Usage: pidofproc [-p pidfile] pathname #
382# #
383# Purpose: This function returns one or more pid(s) for a particular daemon #
384# #
385# Inputs: -p pidfile, use the specified pidfile instead of pidof #
386# pathname, path to the specified program #
387# #
388# Return values (as defined by LSB status codes): #
389# 0 - Success (PIDs to stdout) #
390# 1 - Program is dead, PID file still exists (remaining PIDs output) #
391# 3 - Program is not running (no output) #
392################################################################################
393pidofproc()
394{
395 local pidfile
396 local program
397 local prefix
398 local progname
399 local pidlist
400 local lpids
401 local exitstatus="0"
402
403 # Process arguments
404 while true; do
405 case "${1}" in
406
407 -p)
408 pidfile="${2}"
409 shift 2
410 ;;
411
412 *)
413 program="${1}"
414 if [ -n "${2}" ]; then
415 # Too many arguments
416 # Since this is status, return unknown
417 return 4
418 else
419 break
420 fi
421 ;;
422 esac
423 done
424
425 # If a PID file is not specified, try and find one.
426 if [ -z "${pidfile}" ]; then
427 # Get the program's basename
428 prefix=`echo "${program}" | sed 's/[^/]*$//'`
429
430 if [ -z "${prefix}" ]; then
431 progname="${program}"
432 else
433 progname=`echo "${program}" | sed "s@${prefix}@@"`
434 fi
435
436 # If a PID file exists with that name, assume that is it.
437 if [ -e "/run/${progname}.pid" ]; then
438 pidfile="/run/${progname}.pid"
439 fi
440 fi
441
442 # If a PID file is set and exists, use it.
443 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
444
445 # Use the value in the first line of the pidfile
446 pidlist=`/bin/head -n1 "${pidfile}"`
447 # This can optionally be written as 'sed 1q' to repalce 'head -n1'
448 # should LFS move /bin/head to /usr/bin/head
449 else
450 # Use pidof
451 pidlist=`pidof "${program}"`
452 fi
453
454 # Figure out if all listed PIDs are running.
455 for pid in ${pidlist}; do
456 kill -0 ${pid} 2> /dev/null
457
458 if [ "${?}" -eq "0" ]; then
459 lpids="${lpids}${pid} "
460 else
461 exitstatus="1"
462 fi
463 done
464
465 if [ -z "${lpids}" -a ! -f "${pidfile}" ]; then
466 return 3
467 else
468 echo "${lpids}"
469 return "${exitstatus}"
470 fi
471}
472
473################################################################################
474# statusproc() #
475# Usage: statusproc [-p pidfile] pathname #
476# #
477# Purpose: This function prints the status of a particular daemon to stdout #
478# #
479# Inputs: -p pidfile, use the specified pidfile instead of pidof #
480# pathname, path to the specified program #
481# #
482# Return values: #
483# 0 - Status printed #
484# 1 - Input error. The daemon to check was not specified. #
485################################################################################
486statusproc()
487{
488 local pidfile
489 local pidlist
490
491 if [ "${#}" = "0" ]; then
492 echo "Usage: statusproc [-p pidfle] {program}"
493 exit 1
494 fi
495
496 # Process arguments
497 while true; do
498 case "${1}" in
499
500 -p)
501 pidfile="${2}"
502 shift 2
503 ;;
504
505 *)
506 if [ -n "${2}" ]; then
507 echo "Too many arguments"
508 return 1
509 else
510 break
511 fi
512 ;;
513 esac
514 done
515
516 if [ -n "${pidfile}" ]; then
517 pidlist=`pidofproc -p "${pidfile}" $@`
518 else
519 pidlist=`pidofproc $@`
520 fi
521
522 # Trim trailing blanks
523 pidlist=`echo "${pidlist}" | sed -r 's/ +$//'`
524
525 base="${1##*/}"
526
527 if [ -n "${pidlist}" ]; then
528 /bin/echo -e "${INFO}${base} is running with Process" \
529 "ID(s) ${pidlist}.${NORMAL}"
530 else
531 if [ -n "${base}" -a -e "/run/${base}.pid" ]; then
532 /bin/echo -e "${WARNING}${1} is not running but" \
533 "/run/${base}.pid exists.${NORMAL}"
534 else
535 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
536 /bin/echo -e "${WARNING}${1} is not running" \
537 "but ${pidfile} exists.${NORMAL}"
538 else
539 /bin/echo -e "${INFO}${1} is not running.${NORMAL}"
540 fi
541 fi
542 fi
543}
544
545################################################################################
546# timespec() #
547# #
548# Purpose: An internal utility function to format a timestamp #
549# a boot log file. Sets the STAMP variable. #
550# #
551# Return value: Not used #
552################################################################################
553timespec()
554{
555 STAMP="$(echo `date +"%b %d %T %:z"` `hostname`) "
556 return 0
557}
558
559################################################################################
560# log_success_msg() #
561# Usage: log_success_msg ["message"] #
562# #
563# Purpose: Print a successful status message to the screen and #
564# a boot log file. #
565# #
566# Inputs: $@ - Message #
567# #
568# Return values: Not used #
569################################################################################
570log_success_msg()
571{
572 /bin/echo -n -e "${BMPREFIX}${@}"
573 /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}"
574
575 # Strip non-printable characters from log file
576 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
577
578 timespec
579 /bin/echo -e "${STAMP} ${logmessage} OK" >> ${BOOTLOG}
580
581 return 0
582}
583
584log_success_msg2()
585{
586 /bin/echo -n -e "${BMPREFIX}${@}"
587 /bin/echo -e "${CURS_ZERO}${SUCCESS_PREFIX}${SET_COL}${SUCCESS_SUFFIX}"
588
589 echo " OK" >> ${BOOTLOG}
590
591 return 0
592}
593
594################################################################################
595# log_failure_msg() #
596# Usage: log_failure_msg ["message"] #
597# #
598# Purpose: Print a failure status message to the screen and #
599# a boot log file. #
600# #
601# Inputs: $@ - Message #
602# #
603# Return values: Not used #
604################################################################################
605log_failure_msg()
606{
607 /bin/echo -n -e "${BMPREFIX}${@}"
608 /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}"
609
610 # Strip non-printable characters from log file
611
612 timespec
613 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
614 /bin/echo -e "${STAMP} ${logmessage} FAIL" >> ${BOOTLOG}
615
616 return 0
617}
618
619log_failure_msg2()
620{
621 /bin/echo -n -e "${BMPREFIX}${@}"
622 /bin/echo -e "${CURS_ZERO}${FAILURE_PREFIX}${SET_COL}${FAILURE_SUFFIX}"
623
624 echo "FAIL" >> ${BOOTLOG}
625
626 return 0
627}
628
629################################################################################
630# log_warning_msg() #
631# Usage: log_warning_msg ["message"] #
632# #
633# Purpose: Print a warning status message to the screen and #
634# a boot log file. #
635# #
636# Return values: Not used #
637################################################################################
638log_warning_msg()
639{
640 /bin/echo -n -e "${BMPREFIX}${@}"
641 /bin/echo -e "${CURS_ZERO}${WARNING_PREFIX}${SET_COL}${WARNING_SUFFIX}"
642
643 # Strip non-printable characters from log file
644 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
645 timespec
646 /bin/echo -e "${STAMP} ${logmessage} WARN" >> ${BOOTLOG}
647
648 return 0
649}
650
651log_skip_msg()
652{
653 /bin/echo -n -e "${BMPREFIX}${@}"
654 /bin/echo -e "${CURS_ZERO}${SKIP_PREFIX}${SET_COL}${SKIP_SUFFIX}"
655
656 # Strip non-printable characters from log file
657 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
658 /bin/echo "SKIP" >> ${BOOTLOG}
659
660 return 0
661}
662
663################################################################################
664# log_info_msg() #
665# Usage: log_info_msg message #
666# #
667# Purpose: Print an information message to the screen and #
668# a boot log file. Does not print a trailing newline character. #
669# #
670# Return values: Not used #
671################################################################################
672log_info_msg()
673{
674 /bin/echo -n -e "${BMPREFIX}${@}"
675
676 # Strip non-printable characters from log file
677 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
678 timespec
679 /bin/echo -n -e "${STAMP} ${logmessage}" >> ${BOOTLOG}
680
681 return 0
682}
683
684log_info_msg2()
685{
686 /bin/echo -n -e "${@}"
687
688 # Strip non-printable characters from log file
689 logmessage=`echo "${@}" | sed 's/\\\033[^a-zA-Z]*.//g'`
690 /bin/echo -n -e "${logmessage}" >> ${BOOTLOG}
691
692 return 0
693}
694
695################################################################################
696# evaluate_retval() #
697# Usage: Evaluate a return value and print success or failyure as appropriate #
698# #
699# Purpose: Convenience function to terminate an info message #
700# #
701# Return values: Not used #
702################################################################################
703evaluate_retval()
704{
705 local error_value="${?}"
706
707 if [ ${error_value} = 0 ]; then
708 log_success_msg2
709 else
710 log_failure_msg2
711 fi
712}
713
714################################################################################
715# check_signal() #
716# Usage: check_signal [ -{signal} | {signal} ] #
717# #
718# Purpose: Check for a valid signal. This is not defined by any LSB draft, #
719# however, it is required to check the signals to determine if the #
720# signals chosen are invalid arguments to the other functions. #
721# #
722# Inputs: Accepts a single string value in the form or -{signal} or {signal} #
723# #
724# Return values: #
725# 0 - Success (signal is valid #
726# 1 - Signal is not valid #
727################################################################################
728check_signal()
729{
730 local valsig
731
732 # Add error handling for invalid signals
733 valsig="-ALRM -HUP -INT -KILL -PIPE -POLL -PROF -TERM -USR1 -USR2"
734 valsig="${valsig} -VTALRM -STKFLT -PWR -WINCH -CHLD -URG -TSTP -TTIN"
735 valsig="${valsig} -TTOU -STOP -CONT -ABRT -FPE -ILL -QUIT -SEGV -TRAP"
736 valsig="${valsig} -SYS -EMT -BUS -XCPU -XFSZ -0 -1 -2 -3 -4 -5 -6 -8 -9"
737 valsig="${valsig} -11 -13 -14 -15"
738
739 echo "${valsig}" | grep -- " ${1} " > /dev/null
740
741 if [ "${?}" -eq "0" ]; then
742 return 0
743 else
744 return 1
745 fi
746}
747
748################################################################################
749# check_sig_type() #
750# Usage: check_signal [ -{signal} | {signal} ] #
751# #
752# Purpose: Check if signal is a program termination signal or a control signal #
753# This is not defined by any LSB draft, however, it is required to #
754# check the signals to determine if they are intended to end a #
755# program or simply to control it. #
756# #
757# Inputs: Accepts a single string value in the form or -{signal} or {signal} #
758# #
759# Return values: #
760# 0 - Signal is used for program termination #
761# 1 - Signal is used for program control #
762################################################################################
763check_sig_type()
764{
765 local valsig
766
767 # The list of termination signals (limited to generally used items)
768 valsig="-ALRM -INT -KILL -TERM -PWR -STOP -ABRT -QUIT -2 -3 -6 -9 -14 -15"
769
770 echo "${valsig}" | grep -- " ${1} " > /dev/null
771
772 if [ "${?}" -eq "0" ]; then
773 return 0
774 else
775 return 1
776 fi
777}
778
779################################################################################
780# wait_for_user() #
781# #
782# Purpose: Wait for the user to respond if not a headless system #
783# #
784################################################################################
785wait_for_user()
786{
787 # Wait for the user by default
788 [ "${HEADLESS=0}" = "0" ] && read ENTER
789 return 0
790}
791
792################################################################################
793# is_true() #
794# #
795# Purpose: Utility to test if a variable is true | yes | 1 #
796# #
797################################################################################
798is_true()
799{
800 [ "$1" = "1" ] || [ "$1" = "yes" ] || [ "$1" = "true" ] || [ "$1" = "y" ] ||
801 [ "$1" = "t" ]
802}
803
804# End /lib/lsb/init-functions
Note: See TracBrowser for help on using the repository browser.