source: bootscripts-standard/clfs/init.d/functions@ 91e0c48

Last change on this file since 91e0c48 was 7355219, checked in by Chris Staub <chris@…>, 17 years ago

killproc function uses sleep

  • Property mode set to 100644
File size: 17.4 KB
RevLine 
[7df280d]1#!/bin/bash
[7125722]2########################################################################
3# Begin $rc_base/init.d/functions
4#
5# Description : Run Level Control Functions
6#
7# Authors : Gerard Beekmans - gerard@linuxfromscratch.org
8#
9# Version : 00.00
10#
11# Notes : With code based on Matthias Benkmann's simpleinit-msb
12# http://winterdrache.de/linux/newboot/index.html
13#
14########################################################################
15
16if [ -e /etc/sysconfig/lcd ]; then
17 if [ -e /dev/lcd ]; then
18 source /etc/sysconfig/lcd
19 fi
20fi
21
22if [ -e /etc/sysconfig/bootscripts ]; then
23 source /etc/sysconfig/bootscripts
24fi
25
26## Environmental setup
27# Setup default values for environment
28umask 022
29export PATH="/bin:/usr/bin:/sbin:/usr/sbin"
30
31# Signal sent to running processes to refresh their configuration
32RELOADSIG="HUP"
33
34# Number of seconds between STOPSIG and FALLBACK when stopping processes
35KILLDELAY="3"
36
37## Screen Dimensions
38# Find current screen size
39if [ -z "${COLUMNS}" ]; then
40 COLUMNS=$(stty size)
41 COLUMNS=${COLUMNS##* }
42fi
43
44# When using remote connections, such as a serial port, stty size returns 0
45if [ "${COLUMNS}" = "0" ]; then
46 COLUMNS=80
47fi
48
49## Measurements for positioning result messages
50COL=$((${COLUMNS} - 8))
51WCOL=$((${COL} - 2))
52
[1d02f01]53## Provide an echo that supports -e and -n
54# If formatting is needed, $ECHO should be used
55case "`echo -e -n test`" in
56 -[en]*)
57 ECHO=/bin/echo
58 ;;
59 *)
60 ECHO=echo
61 ;;
62esac
63
64## Set Cursor Position Commands, used via $ECHO
[7125722]65SET_COL="\\033[${COL}G" # at the $COL char
66SET_WCOL="\\033[${WCOL}G" # at the $WCOL char
67CURS_UP="\\033[1A\\033[0G" # Up one line, at the 0'th char
68
[1d02f01]69## Set color commands, used via $ECHO
[7125722]70# Please consult `man console_codes for more information
71# under the "ECMA-48 Set Graphics Rendition" section
72#
73# Warning: when switching from a 8bit to a 9bit font,
74# the linux console will reinterpret the bold (1;) to
75# the top 256 glyphs of the 9bit font. This does
76# not affect framebuffer consoles
77NORMAL="\\033[0;39m" # Standard console grey
78SUCCESS="\\033[1;32m" # Success is green
79WARNING="\\033[1;33m" # Warnings are yellow
80FAILURE="\\033[1;31m" # Failures are red
81INFO="\\033[1;36m" # Information is light cyan
82BRACKET="\\033[1;34m" # Brackets are blue
83
84STRING_LENGTH="0" # the length of the current message
85
86#*******************************************************************************
87# Function - boot_mesg()
88#
89# Purpose: Sending information from bootup scripts to the console
90#
91# Inputs: $1 is the message
92# $2 is the colorcode for the console
93#
94# Outputs: Standard Output
95#
96# Dependencies: - sed for parsing strings.
97# - grep for counting string length.
98#
99# Todo:
100#*******************************************************************************
101boot_mesg()
102{
103 local ECHOPARM=""
104
105 if [ "$LCD_PROG" ]; then
106 LCD_OUT1="${1:0:$LCD_CHAR}"
107 $LCD_PROG "$LCD_OUT1" > /dev/null 2>&1
108 fi
109
110 while true
111 do
112 case "${1}" in
113 -n)
114 ECHOPARM=" -n "
115 shift 1
116 ;;
117 -*)
118 echo "Unknown Option: ${1}"
119 return 1
120 ;;
121 *)
122 break
123 ;;
124 esac
125 done
126
127 ## Figure out the length of what is to be printed to be used
[1d02f01]128 ## for warning messages.
129 STRING_LENGTH=$((${#1} + 1))
[7125722]130
131 # Print the message to the screen
[1d02f01]132 ${ECHO} ${ECHOPARM} -e "${2}${1}"
[7125722]133
134}
135
136boot_mesg_flush()
137{
138 # Reset STRING_LENGTH for next message
139 STRING_LENGTH="0"
140 if [ "$LOGGING" ]; then
141 boot_log "${BOOTMESG}${@}"
142 fi
143}
144
145boot_log()
146{
147 if [ "$LOGGING" ]; then
148 /bin/logger -p local2.info -t bootlog "${DISPLAYLOG} ${1}"
149 else
150 return 0
151 fi
152}
153
154echo_ok()
155{
156 if [ "$LCD_PROG" ]; then
157 if [ "$LCD_LINES" = "2" ]; then
158 LCD_OUT2="[ OK ]"
159 $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
160 else
161 LCD_OUT2="${LCD_OUT1:0:12} OK"
162 $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
[1d02f01]163 fi
[7125722]164 fi
[1d02f01]165 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]"
166 ${ECHO} -e "${NORMAL}"
167 boot_mesg_flush
[7125722]168}
169
170echo_failure()
171{
172 if [ "$LCD_PROG" ]; then
173 if [ "$LCD_LINES" = "2" ]; then
174 LCD_OUT2="[ FAIL ]"
175 $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
176 else
177 LCD_OUT2="${LCD_OUT1:0:10} FAIL"
178 $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
179 fi
180 fi
[1d02f01]181 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]"
182 ${ECHO} -e "${NORMAL}"
183 boot_mesg_flush
[7125722]184}
185
186echo_warning()
187{
188 if [ "$LCD_PROG" ]; then
189 if [ "$LCD_LINES" = "2" ]; then
190 LCD_OUT2="[ WARN ]"
191 $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
192 else
193 LCD_OUT2="${LCD_OUT1:0:10} WARN"
194 $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
[1d02f01]195 fi
[7125722]196 fi
[1d02f01]197 ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]"
198 ${ECHO} -e "${NORMAL}"
199 boot_mesg_flush
[7125722]200}
201
202print_error_msg()
203{
204 echo_failure
205 # $i is inherited by the rc script
206 boot_log "\n\n${i} failed and exited with a return value of ${error_value}."
207 boot_mesg -n "FAILURE:\n\nYou should not be reading this error message.\n\n" ${FAILURE}
208 boot_mesg -n " It means that an unforeseen error took"
209 boot_mesg -n " place in ${i}, which exited with a return value of"
210 boot_mesg " ${error_value}.\n"
211 boot_mesg_flush
212 boot_mesg -n "If you're able to track this"
213 boot_mesg -n " error down to a bug in one of the files provided by"
214 boot_mesg -n " the CLFS book, please be so kind to inform us at"
215 boot_mesg " clfs-dev@cross-lfs.org.\n"
216 boot_mesg_flush
[1d02f01]217 boot_mesg -n "Press Enter to continue..." ${INFO}
218 boot_mesg "" ${NORMAL}
219 read ENTER
[7125722]220}
221
222check_script_status()
223{
224 # $i is inherited by the rc script
225 if [ ! -f ${i} ]; then
226 boot_mesg "${i} is not a valid symlink." ${WARNING}
227 echo_warning
228 continue
229 fi
230
231 if [ ! -x ${i} ]; then
232 boot_mesg "${i} is not executable, skipping." ${WARNING}
233 echo_warning
234 continue
235 fi
236}
237
238evaluate_retval()
239{
240 error_value="${?}"
241
242 if [ ${error_value} = 0 ]; then
243 echo_ok
244 else
245 echo_failure
246 fi
247
248 # This prevents the 'An Unexpected Error Has Occurred' from trivial
249 # errors.
250 return 0
251}
252
253print_status()
254{
255 if [ "${#}" = "0" ]; then
256 echo "Usage: ${0} {success|warning|failure}"
257 return 1
258 fi
259
260 case "${1}" in
261
262 success)
263 echo_ok
264 ;;
265
266 warning)
267 # Leave this extra case in because old scripts
268 # may call it this way.
269 case "${2}" in
270 running)
[1d02f01]271 ${ECHO} -e -n "${CURS_UP}"
272 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
[7125722]273 boot_mesg "Already running." ${WARNING}
274 echo_warning
275 ;;
276 not_running)
[1d02f01]277 ${ECHO} -e -n "${CURS_UP}"
278 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
[7125722]279 boot_mesg "Not running." ${WARNING}
280 echo_warning
281 ;;
282 not_available)
[1d02f01]283 ${ECHO} -e -n "${CURS_UP}"
284 ${ECHO} -e -n "\\033[${STRING_LENGTH}G "
[7125722]285 boot_mesg "Not available." ${WARNING}
286 echo_warning
287 ;;
288 *)
289 # This is how it is supposed to
290 # be called
291 echo_warning
292 ;;
293 esac
294 ;;
295
296 failure)
297 echo_failure
298 ;;
299
300 esac
301
302}
303
304reloadproc()
305{
[1d02f01]306 local pidfile=""
307 local failure=0
308
309 while true
310 do
311 case "${1}" in
312 -p)
313 pidfile="${2}"
314 shift 2
315 ;;
316 -*)
317 log_failure_msg "Unknown Option: ${1}"
318 return 2
319 ;;
320 *)
321 break
322 ;;
323 esac
324 done
325
326 if [ "${#}" -lt "1" ]; then
327 log_failure_msg "Usage: reloadproc [-p pidfile] pathname"
328 return 2
329 fi
330
331 # This will ensure compatibility with previous CLFS Bootscripts
332 if [ -n "${PIDFILE}" ]; then
333 pidfile="${PIDFILE}"
[7125722]334 fi
335
[1d02f01]336 # Is the process running?
337 if [ -z "${pidfile}" ]; then
338 pidofproc -s "${1}"
339 else
340 pidofproc -s -p "${pidfile}" "${1}"
341 fi
[7125722]342
343 if [ -n "${pidlist}" ]; then
344 for pid in ${pidlist}
345 do
346 kill -"${RELOADSIG}" "${pid}" || failure="1"
347 done
348
349 (exit ${failure})
350 evaluate_retval
351
352 else
353 boot_mesg "Process ${1} not running." ${WARNING}
354 echo_warning
355 fi
356}
357
358statusproc()
359{
[1d02f01]360 local pidfile=""
361 local base=""
362 local ret=""
363
364 while true
365 do
366 case "${1}" in
367 -p)
368 pidfile="${2}"
369 shift 2
370 ;;
371 -*)
372 log_failure_msg "Unknown Option: ${1}"
373 return 2
374 ;;
375 *)
376 break
377 ;;
378 esac
379 done
380
381 if [ "${#}" != "1" ]; then
382 shift 1
383 log_failure_msg "Usage: statusproc [-p pidfile] pathname"
384 return 2
[7125722]385 fi
386
[1d02f01]387 # Get the process basename
388 base="${1##*/}"
389
390 # This will ensure compatibility with previous CLFS Bootscripts
391 if [ -n "${PIDFILE}" ]; then
392 pidfile="${PIDFILE}"
393 fi
394
395 # Is the process running?
396 if [ -z "${pidfile}" ]; then
397 pidofproc -s "${1}"
398 else
399 pidofproc -s -p "${pidfile}" "${1}"
400 fi
401
402 # Store the return status
403 ret=$?
[7125722]404
405 if [ -n "${pidlist}" ]; then
[1d02f01]406 ${ECHO} -e "${INFO}${base} is running with Process"\
[7125722]407 "ID(s) ${pidlist}.${NORMAL}"
408 else
409 if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then
[1d02f01]410 ${ECHO} -e "${WARNING}${1} is not running but"\
[7125722]411 "/var/run/${base}.pid exists.${NORMAL}"
412 else
[1d02f01]413 if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
414 ${ECHO} -e "${WARNING}${1} is not running"\
415 "but ${pidfile} exists.${NORMAL}"
[7125722]416 else
[1d02f01]417 ${ECHO} -e "${INFO}${1} is not running.${NORMAL}"
[7125722]418 fi
419 fi
420 fi
[1d02f01]421
422 # Return the status from pidofproc
423 return $ret
[7125722]424}
425
426# The below functions are documented in the LSB-generic 2.1.0
427
428#*******************************************************************************
429# Function - pidofproc [-s] [-p pidfile] pathname
430#
431# Purpose: This function returns one or more pid(s) for a particular daemon
432#
433# Inputs: -p pidfile, use the specified pidfile instead of pidof
434# pathname, path to the specified program
435#
436# Outputs: return 0 - Success, pid's in stdout
437# return 1 - Program is dead, pidfile exists
438# return 2 - Invalid or excessive number of arguments,
439# warning in stdout
440# return 3 - Program is not running
441#
442# Dependencies: pidof, echo, head
443#
444# Todo: Remove dependency on head
445# This depreciates getpids
446# Test changes to pidof
447#
448#*******************************************************************************
449pidofproc()
450{
451 local pidfile=""
452 local lpids=""
453 local silent=""
454 pidlist=""
455 while true
456 do
457 case "${1}" in
458 -p)
459 pidfile="${2}"
460 shift 2
461 ;;
462
463 -s)
464 # Added for legacy opperation of getpids
465 # eliminates several '> /dev/null'
466 silent="1"
467 shift 1
468 ;;
469 -*)
470 log_failure_msg "Unknown Option: ${1}"
471 return 2
472 ;;
473 *)
474 break
475 ;;
476 esac
477 done
478
479 if [ "${#}" != "1" ]; then
480 shift 1
481 log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname"
482 return 2
483 fi
484
485 if [ -n "${pidfile}" ]; then
486 if [ ! -r "${pidfile}" ]; then
487 return 3 # Program is not running
488 fi
489
490 lpids=`head -n 1 ${pidfile}`
491 for pid in ${lpids}
492 do
493 if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then
[1d02f01]494 kill -0 "${pid}" 2>/dev/null &&
[7125722]495 pidlist="${pidlist} ${pid}"
496 fi
497
[1d02f01]498 if [ "${silent}" != "1" ]; then
[7125722]499 echo "${pidlist}"
500 fi
501
502 test -z "${pidlist}" &&
503 # Program is dead, pidfile exists
504 return 1
505 # else
506 return 0
507 done
508
509 else
510 pidlist=`pidof -o $$ -o $PPID -x "$1"`
[1d02f01]511 if [ "${silent}" != "1" ]; then
[7125722]512 echo "${pidlist}"
513 fi
514
515 # Get provide correct running status
516 if [ -n "${pidlist}" ]; then
517 return 0
518 else
519 return 3
520 fi
521
522 fi
523
524 if [ "$?" != "0" ]; then
525 return 3 # Program is not running
526 fi
527}
528
529# This will ensure compatibility with previous CLFS Bootscripts
530getpids()
531{
532 if [ -z "${PIDFILE}" ]; then
533 pidofproc -s -p "${PIDFILE}" $@
534 else
535 pidofproc -s $@
536 fi
537 base="${1##*/}"
538}
539
540#*******************************************************************************
541# Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]
542#
543# Purpose: This runs the specified program as a daemon
544#
545# Inputs: -f, run the program even if it is already running
546# -n nicelevel, specifies a nice level. See nice(1).
547# -p pidfile, uses the specified pidfile
548# pathname, pathname to the specified program
549# args, arguments to pass to specified program
550#
551# Outputs: return 0 - Success
552# return 2 - Invalid of excessive number of arguments,
553# warning in stdout
554# return 4 - Program or service status is unknown
555#
556# Dependencies: nice
557#
558# Todo: LSB says this should be called start_daemon
559# LSB does not say that it should call evaluate_retval
560# It checks for PIDFILE, which is deprecated.
561# Will be removed after BLFS 6.0
562# loadproc returns 0 if program is already running, not LSB compliant
563#
564#*******************************************************************************
565loadproc()
566{
567 local pidfile=""
568 local forcestart=""
569 local nicelevel="10"
570
571# This will ensure compatibility with previous CLFS Bootscripts
572 if [ -n "${PIDFILE}" ]; then
573 pidfile="${PIDFILE}"
574 fi
575
576 while true
577 do
578 case "${1}" in
579 -f)
580 forcestart="1"
581 shift 1
582 ;;
583 -n)
584 nicelevel="${2}"
585 shift 2
586 ;;
587 -p)
588 pidfile="${2}"
589 shift 2
590 ;;
591 -*)
592 log_failure_msg "Unknown Option: ${1}"
593 return 2 #invalid or excess argument(s)
594 ;;
595 *)
596 break
597 ;;
598 esac
599 done
600
601 if [ "${#}" = "0" ]; then
602 log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]"
603 return 2 #invalid or excess argument(s)
604 fi
605
606 if [ -z "${forcestart}" ]; then
607 if [ -z "${pidfile}" ]; then
608 pidofproc -s "${1}"
609 else
610 pidofproc -s -p "${pidfile}" "${1}"
611 fi
612
613 case "${?}" in
614 0)
615 log_warning_msg "Unable to continue: ${1} is running"
616 return 0 # 4
617 ;;
618 1)
619 log_warning_msg "Unable to continue: ${pidfile} exists"
620 return 0 # 4
621 ;;
622 3)
623 ;;
624 *)
625 log_failure_msg "Unknown error code from pidofproc: ${?}"
626 return 4
627 ;;
628 esac
629 fi
630
631 nice -n "${nicelevel}" "${@}"
632 evaluate_retval # This is "Probably" not LSB compliant, but required to be compatible with older bootscripts
633 return 0
634}
635
636#*******************************************************************************
637# Function - killproc [-p pidfile] pathname [signal]
638#
639# Purpose:
640#
641# Inputs: -p pidfile, uses the specified pidfile
642# pathname, pathname to the specified program
643# signal, send this signal to pathname
644#
645# Outputs: return 0 - Success
646# return 2 - Invalid of excessive number of arguments,
647# warning in stdout
648# return 4 - Unknown Status
649#
[7355219]650# Dependencies: kill, sleep
[7125722]651#
652# Todo: LSB does not say that it should call evaluate_retval
653# It checks for PIDFILE, which is deprecated.
654# Will be removed after BLFS 6.0
655#
656#*******************************************************************************
657killproc()
658{
659 local pidfile=""
[1d02f01]660 local killsig=TERM # default signal is SIGTERM
[7125722]661 pidlist=""
662
[1d02f01]663 # This will ensure compatibility with previous CLFS Bootscripts
[7125722]664 if [ -n "${PIDFILE}" ]; then
665 pidfile="${PIDFILE}"
666 fi
667
668 while true
669 do
670 case "${1}" in
671 -p)
672 pidfile="${2}"
673 shift 2
674 ;;
675 -*)
676 log_failure_msg "Unknown Option: ${1}"
677 return 2
[1d02f01]678 ;;
[7125722]679 *)
680 break
681 ;;
682 esac
683 done
684
685 if [ "${#}" = "2" ]; then
686 killsig="${2}"
687 elif [ "${#}" != "1" ]; then
688 shift 2
689 log_failure_msg "Usage: killproc [-p pidfile] pathname [signal]"
690 return 2
691 fi
692
[1d02f01]693 # Is the process running?
[7125722]694 if [ -z "${pidfile}" ]; then
695 pidofproc -s "${1}"
696 else
697 pidofproc -s -p "${pidfile}" "${1}"
698 fi
699
[1d02f01]700 # If running, send the signal
[7125722]701 if [ -n "${pidlist}" ]; then
702 for pid in ${pidlist}
703 do
[1d02f01]704 kill -${killsig} ${pid} 2>/dev/null
705
706 # Wait up to 3 seconds, for ${pid} to terminate
707 case "${killsig}" in
708 TERM|SIGTERM|KILL|SIGKILL)
709 # sleep in 1/10ths of seconds and
710 # multiply KILLDELAY by 10
711 local dtime="${KILLDELAY}0"
[7125722]712 while [ "${dtime}" != "0" ]
713 do
714 kill -0 ${pid} 2>/dev/null || break
[1d02f01]715 sleep 0.1
[7125722]716 dtime=$(( ${dtime} - 1))
717 done
718 # If ${pid} is still running, kill it
719 kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null
[1d02f01]720 ;;
721 esac
[7125722]722 done
723
[1d02f01]724 # Check if the process is still running if we tried to stop it
725 case "${killsig}" in
726 TERM|SIGTERM|KILL|SIGKILL)
727 if [ -z "${pidfile}" ]; then
728 pidofproc -s "${1}"
729 else
730 pidofproc -s -p "${pidfile}" "${1}"
731 fi
[7125722]732
733 # Program was terminated
734 if [ "$?" != "0" ]; then
[1d02f01]735 # Remove the pidfile if necessary
[7125722]736 if [ -f "${pidfile}" ]; then
737 rm -f "${pidfile}"
738 fi
739 echo_ok
740 return 0
741 else # Program is still running
742 echo_failure
743 return 4 # Unknown Status
744 fi
[1d02f01]745 ;;
746 *)
747 # Just see if the kill returned successfully
748 evaluate_retval
749 ;;
750 esac
751 else # process not running
[7125722]752 print_status warning not_running
753 fi
754}
755
756
757#*******************************************************************************
758# Function - log_success_msg "message"
759#
760# Purpose: Print a success message
761#
762# Inputs: $@ - Message
763#
764# Outputs: Text output to screen
765#
766# Dependencies: echo
767#
768# Todo: logging
769#
770#*******************************************************************************
771log_success_msg()
772{
[1d02f01]773 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
774 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}"
[7125722]775 return 0
776}
777
778#*******************************************************************************
779# Function - log_failure_msg "message"
780#
781# Purpose: Print a failure message
782#
783# Inputs: $@ - Message
784#
785# Outputs: Text output to screen
786#
787# Dependencies: echo
788#
789# Todo: logging
790#
791#*******************************************************************************
792log_failure_msg() {
[1d02f01]793 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
794 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}"
[7125722]795 return 0
796}
797
798#*******************************************************************************
799# Function - log_warning_msg "message"
800#
801# Purpose: print a warning message
802#
803# Inputs: $@ - Message
804#
805# Outputs: Text output to screen
806#
807# Dependencies: echo
808#
809# Todo: logging
810#
811#*******************************************************************************
812log_warning_msg() {
[1d02f01]813 ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
814 ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}"
[7125722]815 return 0
816}
817
818# End $rc_base/init.d/functions
Note: See TracBrowser for help on using the repository browser.