[arch-projects] [initscripts] [PATCH 00/13] A new rag rug roll (rebased)
* Cleaned this up a bit more. * Tweak status() to make live a bit simpler * Dropped the remaining old patches (for now) Kurt J. Bosch (13): functions/rc.single: Clean up whitespace rc.sysinit: Fix stat_busy block indentation functions: Get rid of superfluous braces in udevd_modprobe() functions: Add missing quotes in mount_all() functions/rc.multi: Strip paths from binaries rc.sysinit/functions: Refactor kill_everything/fsck_all/mount_all rc.sysinit: Declare $FORCEFSCK read-only to prevent custom hooks from messing functions/rc.sysinit: Refactor fsck-redirection to prevent breakage functions: Sanitize status() behaviour to make it more intuitive rc.sysinit: Simplify setting hostname by using status() even with redirection now functions: Deprecate in_array(), Add replacement is_in_array() functions: Add stop_all_daemons() and related *_prestopdaemons hook functions: Speed up reboot/shutdown by recognizing killall5 exit code 2 functions | 134 +++++++++++++++++++++++++++++++++++------------------------- rc.multi | 2 +- rc.single | 4 +- rc.sysinit | 31 +++++++++++--- 4 files changed, 106 insertions(+), 65 deletions(-)
--- functions | 2 +- rc.single | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/functions b/functions index bcc97c1..f82110d 100644 --- a/functions +++ b/functions @@ -320,7 +320,7 @@ udevd_modprobe() { udevadm settle --timeout=${UDEV_TIMEOUT:-30} run_hook "${1}_udevsettled" - + # in case loading a module changed the display mode calc_columns } diff --git a/rc.single b/rc.single index d630736..d1efd41 100755 --- a/rc.single +++ b/rc.single @@ -12,10 +12,10 @@ run_hook single_start if [[ $PREVLEVEL != N ]]; then kill_everything single - + # start up our mini logger until syslog takes over minilogd - + # Start/trigger UDev, load MODULES and settle UDev udevd_modprobe single fi -- 1.7.1
--- rc.sysinit | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 7b086fa..cb0144c 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -231,7 +231,7 @@ fi # Flush old locale settings and set user defined locale stat_busy "Setting Locale: ${LOCALE:=en_US}" echo "export LANG=$LOCALE" > /etc/profile.d/locale.sh && - chmod 0755 /etc/profile.d/locale.sh && stat_done || stat_fail +chmod 0755 /etc/profile.d/locale.sh && stat_done || stat_fail if [[ ${LOCALE,,} =~ utf ]]; then stat_busy "Setting Consoles to UTF-8 mode" -- 1.7.1
--- functions | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/functions b/functions index f82110d..71b49e3 100644 --- a/functions +++ b/functions @@ -305,7 +305,7 @@ udevd_modprobe() { # This is used to determine which hooks to run. status "Starting UDev Daemon" udevd --daemon - run_hook "${1}_udevlaunched" + run_hook "$1_udevlaunched" stat_busy "Triggering UDev uevents" udevadm trigger --action=add --type=subsystems @@ -319,7 +319,7 @@ udevd_modprobe() { status "Waiting for UDev uevents to be processed" \ udevadm settle --timeout=${UDEV_TIMEOUT:-30} - run_hook "${1}_udevsettled" + run_hook "$1_udevsettled" # in case loading a module changed the display mode calc_columns -- 1.7.1
--- functions | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/functions b/functions index 71b49e3..ec043b6 100644 --- a/functions +++ b/functions @@ -417,7 +417,7 @@ fsck_reboot() { mount_all() { stat_busy "Mounting Local Filesystems" run_hook sysinit_premount - mount -a -t $NETFS -O no_netdev + mount -a -t "$NETFS" -O no_netdev run_hook sysinit_postmount stat_done } -- 1.7.1
Now that we set PATH in functions, we can use is everywhere. --- functions | 42 +++++++++++++++++++++--------------------- rc.multi | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/functions b/functions index ec043b6..7acb855 100644 --- a/functions +++ b/functions @@ -20,12 +20,12 @@ calc_columns () { USECOLOR="" elif [[ -t 0 ]]; then # stty will fail when stdin isn't a terminal - STAT_COL="$(/bin/stty size)" + STAT_COL="$(stty size)" # stty gives "rows cols"; strip the rows number, we just want columns STAT_COL="${STAT_COL##* }" - elif /bin/tput cols &>/dev/null; then + elif tput cols &>/dev/null; then # is /usr/share/terminfo already mounted, and TERM recognized? - STAT_COL=$(/bin/tput cols) + STAT_COL=$(tput cols) fi if (( STAT_COL == 0 )); then # if output was 0 (serial console), set default width to 80 @@ -50,7 +50,7 @@ calc_columns () { calc_columns # disable colors on broken terminals -TERM_COLORS="$(/bin/tput colors 2>/dev/null)" +TERM_COLORS="$(tput colors 2>/dev/null)" if (( $? != 3 )); then case $TERM_COLORS in *[!0-9]*) USECOLOR="";; @@ -75,17 +75,17 @@ fi # set colors if [[ $USECOLOR = [yY][eE][sS] ]]; then - if /bin/tput setaf 0 &>/dev/null; then + if tput setaf 0 &>/dev/null; then C_CLEAR="$(tput sgr0)" # clear text - C_MAIN="${C_CLEAR}$(/bin/tput bold)" # main text - C_OTHER="${C_MAIN}$(/bin/tput setaf 4)" # prefix & brackets - C_SEPARATOR="${C_MAIN}$(/bin/tput setaf 0)" # separator - C_BUSY="${C_CLEAR}$(/bin/tput setaf 6)" # busy - C_FAIL="${C_MAIN}$(/bin/tput setaf 1)" # failed + C_MAIN="${C_CLEAR}$(tput bold)" # main text + C_OTHER="${C_MAIN}$(tput setaf 4)" # prefix & brackets + C_SEPARATOR="${C_MAIN}$(tput setaf 0)" # separator + C_BUSY="${C_CLEAR}$(tput setaf 6)" # busy + C_FAIL="${C_MAIN}$(tput setaf 1)" # failed C_DONE="${C_MAIN}" # completed - C_BKGD="${C_MAIN}$(/bin/tput setaf 5)" # backgrounded + C_BKGD="${C_MAIN}$(tput setaf 5)" # backgrounded C_H1="${C_MAIN}" # highlight text 1 - C_H2="${C_MAIN}$(/bin/tput setaf 6)" # highlight text 2 + C_H2="${C_MAIN}$(tput setaf 6)" # highlight text 2 else C_CLEAR="\e[m" # clear text C_MAIN="\e[;1m" # main text @@ -179,12 +179,12 @@ in_array() { # daemons: add_daemon() { - [[ -d /run/daemons ]] || /bin/mkdir -p /run/daemons + [[ -d /run/daemons ]] || mkdir -p /run/daemons >| /run/daemons/"$1" } rm_daemon() { - /bin/rm -f /run/daemons/"$1" + rm -f /run/daemons/"$1" } ck_daemon() { @@ -287,13 +287,13 @@ kill_everything() { # Terminate all processes stat_busy "Sending SIGTERM To Processes" run_hook "$1_prekillall" - /sbin/killall5 -15 ${omit_pids[@]/#/-o } &>/dev/null - /bin/sleep 5 + killall5 -15 ${omit_pids[@]/#/-o } &>/dev/null + sleep 5 stat_done stat_busy "Sending SIGKILL To Processes" - /sbin/killall5 -9 ${omit_pids[@]/#/-o } &>/dev/null - /bin/sleep 1 + killall5 -9 ${omit_pids[@]/#/-o } &>/dev/null + sleep 1 stat_done run_hook "$1_postkillall" @@ -329,8 +329,8 @@ activate_vgs() { [[ $USELVM = [yY][eE][sS] && -x $(type -P lvm) && -d /sys/block ]] || return 0 # Kernel 2.6.x, LVM2 groups stat_busy "Activating LVM2 groups" - /sbin/modprobe -q dm-mod 2>/dev/null - /sbin/vgchange --sysinit -a y >/dev/null + modprobe -q dm-mod 2>/dev/null + vgchange --sysinit -a y >/dev/null (( $? == 0 )) && stat_done || stat_fail } @@ -496,7 +496,7 @@ set_consolefont() { [[ $CONSOLEMAP && ${LOCALE,,} =~ utf ]] && CONSOLEMAP="" local i for i in /dev/tty[0-9]*; do - /usr/bin/setfont ${CONSOLEMAP:+-m ${CONSOLEMAP}} \ + setfont ${CONSOLEMAP:+-m ${CONSOLEMAP}} \ $CONSOLEFONT -C ${i} &>/dev/null done if (( $? )); then diff --git a/rc.multi b/rc.multi index b801fb6..16fa83a 100755 --- a/rc.multi +++ b/rc.multi @@ -9,7 +9,7 @@ run_hook multi_start # Load sysctl variables if sysctl.conf is present -[[ -r /etc/sysctl.conf ]] && /sbin/sysctl -q -p &>/dev/null +[[ -r /etc/sysctl.conf ]] && sysctl -q -p &>/dev/null # Start daemons for daemon in "${DAEMONS[@]}"; do -- 1.7.1
Genaral scheme is: run_hook pre_foo if [[$WE_WANT_TO_DO_FOO]]]; then stat_busy "Doing foo" if [[$PRECONDITIONS_FOR_FOO_NOT_SATISFIED]]; then stat_fail else ... stat_done fi fi run hook post_foo rc.sysinit ----------- run_hook pre_foo [[$WE_WANT_TO_DO_FOO]] && status "Doing foo" foo run hook post_foo functions ------------ foo() { [[$PRECONDITIONS_FOR_FOO_NOT_SATISFIED]] && return 1 ... } Suggested-by: Tom Gundersen <teg@jklm.no> --- functions | 26 +++++++------------------- rc.sysinit | 24 +++++++++++++++++++++--- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/functions b/functions index 7acb855..c68a4a6 100644 --- a/functions +++ b/functions @@ -284,9 +284,10 @@ kill_everything() { ck_daemon ${DAEMONS[i]#@} || stop_daemon ${DAEMONS[i]#@} done + run_hook "$1_prekillall" + # Terminate all processes stat_busy "Sending SIGTERM To Processes" - run_hook "$1_prekillall" killall5 -15 ${omit_pids[@]/#/-o } &>/dev/null sleep 5 stat_done @@ -360,23 +361,14 @@ read_crypttab() { return $failed } +# Filesystem functions +# These can be overridden for customizations like shutdown/loop-fsck. NETFS="nonfs,nonfs4,nosmbfs,nocifs,nocodafs,noncpfs,nosysfs,noshfs,nofuse,nofuseblk,noglusterfs,nodavfs" # Check local filesystems fsck_all() { - [[ -x $(type -P fsck) ]] || return 0 - stat_busy "Checking Filesystems" - FSCK_OUT=/dev/stdout - FSCK_ERR=/dev/stdout - FSCK_FD= - FORCEFSCK= - [[ -f /forcefsck ]] || in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" - run_hook sysinit_prefsck - fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK >|$FSCK_OUT 2>|$FSCK_ERR - local -r fsckret=$? - (( fsckret <= 1 )) && stat_done || stat_fail - run_hook sysinit_postfsck - return $fsckret + fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK >|$FSCK_OUT 2>|$FSCK_ERR + return $? } # Single-user login and/or automatic reboot after fsck (if needed) @@ -415,11 +407,7 @@ fsck_reboot() { } mount_all() { - stat_busy "Mounting Local Filesystems" - run_hook sysinit_premount - mount -a -t "$NETFS" -O no_netdev - run_hook sysinit_postmount - stat_done + mount -a -t "$NETFS" -O no_netdev } bootlogd_stop() { diff --git a/rc.sysinit b/rc.sysinit index cb0144c..c3610dc 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -174,9 +174,24 @@ if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then fi # Check filesystems -fsck_all +FSCK_OUT=/dev/stdout +FSCK_ERR=/dev/stdout +FSCK_FD= +FORCEFSCK= +[[ -f /forcefsck ]] || is_in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" +run_hook sysinit_prefsck +if [[ -x $(type -P fsck) ]]; then + stat_busy "Checking Filesystems" + fsck_all + declare -r fsckret=$? + (( fsckret <= 1 )) && stat_done || stat_fail +else + declare -r fsckret=0 +fi +run_hook sysinit_postfsck + # Single-user login and/or automatic reboot if needed -fsck_reboot $? +fsck_reboot $fsckret status "Remounting Root Read/Write" \ mount -n -o remount,rw / @@ -193,7 +208,10 @@ if [[ ! -L /etc/mtab ]]; then fi # now mount all the local filesystems -mount_all +run_hook sysinit_premount +status "Mounting Local Filesystems" \ + mount_all +run_hook sysinit_postmount # enable monitoring of lvm2 groups, now that the filesystems are mounted rw [[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && -- 1.7.1
Genaral scheme for hook positions is now: run_hook pre_foo if [[$WE_WANT_TO_DO_FOO]]]; then stat_busy "Doing foo" if [[$PRECONDITIONS_FOR_FOO_NOT_SATISFIED]]; then stat_fail else ... stat_done fi fi run hook post_foo rc.sysinit ----------- run_hook pre_foo [[$WE_WANT_TO_DO_FOO]] && status "Doing foo" foo run hook post_foo functions ------------ foo() { [[$PRECONDITIONS_FOR_FOO_NOT_SATISFIED]] && return 1 ... } Rationale Following this scheme as close as possible (without duplicating code and status messages) makes stuff more readable and uniform. Splitting kill_everything() into two new functions stop_all_daemons() and kill_all() also allows customization of either daemons stopping or process killing in an easy way. Suggested-by: Tom Gundersen <teg@jklm.no> --- functions | 36 +++++++++++------------------------- rc.shutdown | 8 +++++++- rc.single | 9 ++++++++- rc.sysinit | 24 +++++++++++++++++++++--- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/functions b/functions index 7acb855..fd18694 100644 --- a/functions +++ b/functions @@ -265,10 +265,10 @@ add_omit_pids() { omit_pids+=( $@ ) } - -kill_everything() { - # $1 = where we are being called from. - # This is used to determine which hooks to run. +# Stop all daemons +# This function should *never* ever perform any other actions beside calling stop_daemon()! +# It might be used by a splash system etc. to get a list of daemons to be stopped. +stop_all_daemons() { # Find daemons NOT in the DAEMONS array. Shut these down first local daemon for daemon in /run/daemons/*; do @@ -283,10 +283,11 @@ kill_everything() { [[ ${DAEMONS[i]} = '!'* ]] && continue ck_daemon ${DAEMONS[i]#@} || stop_daemon ${DAEMONS[i]#@} done +} +kill_all() { # Terminate all processes stat_busy "Sending SIGTERM To Processes" - run_hook "$1_prekillall" killall5 -15 ${omit_pids[@]/#/-o } &>/dev/null sleep 5 stat_done @@ -295,8 +296,6 @@ kill_everything() { killall5 -9 ${omit_pids[@]/#/-o } &>/dev/null sleep 1 stat_done - - run_hook "$1_postkillall" } # Start/trigger UDev, load MODULES and settle UDev @@ -360,23 +359,14 @@ read_crypttab() { return $failed } +# Filesystem functions +# These can be overridden/reused for customizations like shutdown/loop-fsck. NETFS="nonfs,nonfs4,nosmbfs,nocifs,nocodafs,noncpfs,nosysfs,noshfs,nofuse,nofuseblk,noglusterfs,nodavfs" # Check local filesystems fsck_all() { - [[ -x $(type -P fsck) ]] || return 0 - stat_busy "Checking Filesystems" - FSCK_OUT=/dev/stdout - FSCK_ERR=/dev/stdout - FSCK_FD= - FORCEFSCK= - [[ -f /forcefsck ]] || in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" - run_hook sysinit_prefsck - fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK >|$FSCK_OUT 2>|$FSCK_ERR - local -r fsckret=$? - (( fsckret <= 1 )) && stat_done || stat_fail - run_hook sysinit_postfsck - return $fsckret + fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK >|$FSCK_OUT 2>|$FSCK_ERR + return $? } # Single-user login and/or automatic reboot after fsck (if needed) @@ -415,11 +405,7 @@ fsck_reboot() { } mount_all() { - stat_busy "Mounting Local Filesystems" - run_hook sysinit_premount - mount -a -t "$NETFS" -O no_netdev - run_hook sysinit_postmount - stat_done + mount -a -t "$NETFS" -O no_netdev } bootlogd_stop() { diff --git a/rc.shutdown b/rc.shutdown index fe42797..ed87eec 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -17,7 +17,13 @@ echo " " [[ -x /etc/rc.local.shutdown ]] && /etc/rc.local.shutdown -kill_everything shutdown +stop_all_daemons + +run_hook shutdown_prekillall + +kill_all + +run_hook shutdown_postkillall stat_busy "Saving Random Seed" RANDOM_SEED=/var/lib/misc/random-seed diff --git a/rc.single b/rc.single index d1efd41..21fe3be 100755 --- a/rc.single +++ b/rc.single @@ -11,7 +11,14 @@ export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" run_hook single_start if [[ $PREVLEVEL != N ]]; then - kill_everything single + + stop_all_daemons + + run_hook single_prekillall + + kill_all + + run_hook single_postkillall # start up our mini logger until syslog takes over minilogd diff --git a/rc.sysinit b/rc.sysinit index cb0144c..c3610dc 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -174,9 +174,24 @@ if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then fi # Check filesystems -fsck_all +FSCK_OUT=/dev/stdout +FSCK_ERR=/dev/stdout +FSCK_FD= +FORCEFSCK= +[[ -f /forcefsck ]] || is_in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" +run_hook sysinit_prefsck +if [[ -x $(type -P fsck) ]]; then + stat_busy "Checking Filesystems" + fsck_all + declare -r fsckret=$? + (( fsckret <= 1 )) && stat_done || stat_fail +else + declare -r fsckret=0 +fi +run_hook sysinit_postfsck + # Single-user login and/or automatic reboot if needed -fsck_reboot $? +fsck_reboot $fsckret status "Remounting Root Read/Write" \ mount -n -o remount,rw / @@ -193,7 +208,10 @@ if [[ ! -L /etc/mtab ]]; then fi # now mount all the local filesystems -mount_all +run_hook sysinit_premount +status "Mounting Local Filesystems" \ + mount_all +run_hook sysinit_postmount # enable monitoring of lvm2 groups, now that the filesystems are mounted rw [[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && -- 1.7.1
--- rc.sysinit | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index c3610dc..f64c9ad 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -179,6 +179,7 @@ FSCK_ERR=/dev/stdout FSCK_FD= FORCEFSCK= [[ -f /forcefsck ]] || is_in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" +declare -r FORCEFSCK run_hook sysinit_prefsck if [[ -x $(type -P fsck) ]]; then stat_busy "Checking Filesystems" -- 1.7.1
$FSCK_OUT/$FSCK_ERR might not be set when: * unset in some custom sysinit_prefsck hook * calling fsck() from a shutdown hook --- functions | 2 +- rc.sysinit | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/functions b/functions index c68a4a6..70b4bcf 100644 --- a/functions +++ b/functions @@ -367,7 +367,7 @@ NETFS="nonfs,nonfs4,nosmbfs,nocifs,nocodafs,noncpfs,nosysfs,noshfs,nofuse,nofuse # Check local filesystems fsck_all() { - fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK >|$FSCK_OUT 2>|$FSCK_ERR + fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK return $? } diff --git a/rc.sysinit b/rc.sysinit index f64c9ad..5814007 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -174,8 +174,8 @@ if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then fi # Check filesystems -FSCK_OUT=/dev/stdout -FSCK_ERR=/dev/stdout +FSCK_OUT= +FSCK_ERR= FSCK_FD= FORCEFSCK= [[ -f /forcefsck ]] || is_in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f" @@ -183,7 +183,7 @@ declare -r FORCEFSCK run_hook sysinit_prefsck if [[ -x $(type -P fsck) ]]; then stat_busy "Checking Filesystems" - fsck_all + fsck_all >|${FSCK_OUT:-/dev/stdout} 2>|${FSCK_ERR:-/dev/stdout} declare -r fsckret=$? (( fsckret <= 1 )) && stat_done || stat_fail else -- 1.7.1
* Refactor to return the actual exit code (and get rid of simple if construct) The exit code returned by the given command might be useful/expected, so don't discard but return it. * Do not redirect stdout/stderr, but allow the caller to do it status() did stdout/stderr redirection to /dev/null when calling the given command since the very beginning (commit fd8fde03). This is not as flexible and intuitive as it could be. It is much better to let the caller do any redirections wanted. --- functions | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/functions b/functions index 70b4bcf..0c4c9b1 100644 --- a/functions +++ b/functions @@ -153,15 +153,16 @@ stat_die() { exit ${1:-1} } +# Avoid stolen messages if status() is called with stdout redirection +exec {RC_FUNCTIONS_STDOUT_FD}>&1 + status() { - stat_busy "$1" + stat_busy "$1" >&${RC_FUNCTIONS_STDOUT_FD} shift - if "$@" &>/dev/null; then - stat_done - return 0 - fi - stat_fail - return 1 + "$@" + local $ret=$? + { (( $ret == 0 )) && stat_done || stat_fail ;} >&${RC_FUNCTIONS_STDOUT_FD} + return $ret } # usage : in_array( $needle, $haystack ) -- 1.7.1
* Refactor to return the actual exit code (and get rid of simple if construct) The exit code returned by the given command might be useful/expected, so don't discard but return it. * Do not redirect stdout/stderr, but allow the caller to do it status() did stdout/stderr redirection to /dev/null when calling the given command since the very beginning (commit fd8fde03). This is not as flexible and intuitive as it could be. It is much better to let the caller do any redirections wanted. --- functions | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/functions b/functions index 70b4bcf..3f9f004 100644 --- a/functions +++ b/functions @@ -153,15 +153,16 @@ stat_die() { exit ${1:-1} } +# Avoid stolen messages if status() is called with stdout redirection +exec {RC_FUNCTIONS_STDOUT_FD}>&1 + status() { - stat_busy "$1" + stat_busy "$1" >&${RC_FUNCTIONS_STDOUT_FD} shift - if "$@" &>/dev/null; then - stat_done - return 0 - fi - stat_fail - return 1 + "$@" + local ret=$? + { (( $ret == 0 )) && stat_done || stat_fail ;} >&${RC_FUNCTIONS_STDOUT_FD} + return $ret } # usage : in_array( $needle, $haystack ) -- 1.7.1
--- rc.sysinit | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 5814007..7a12d1c 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -243,8 +243,8 @@ stat_busy "Removing Leftover Files" stat_done if [[ $HOSTNAME ]]; then - stat_busy "Setting Hostname: $HOSTNAME" - echo "$HOSTNAME" >| /proc/sys/kernel/hostname && stat_done || stat_fail + status "Setting Hostname: $HOSTNAME" \ + echo "$HOSTNAME" >| /proc/sys/kernel/hostname fi # Flush old locale settings and set user defined locale -- 1.7.1
* in_array() strips '@' and therefore the name is missleading. * For checking DAEMONS, ck_autostart() should be used. --- functions | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) diff --git a/functions b/functions index 0c4c9b1..7054f60 100644 --- a/functions +++ b/functions @@ -165,10 +165,23 @@ status() { return $ret } -# usage : in_array( $needle, $haystack ) +# usage : is_in_array( $needle, $haystack ) # return : 0 - found # 1 - not found +# Note: For checking DAEMONS, ck_autostart() should be used! +is_in_array() { + local needle=$1; shift + local item + for item; do + [[ $item = $needle ]] && return 0 + done + return 1 # Not Found +} + +# This is deprecated! +# It strips '@' and therefore the name is missleading. in_array() { + echo "WARNING: Call to deprecated function in_array() from $0" >&2 local needle=$1; shift local item for item; do @@ -275,7 +288,7 @@ kill_everything() { for daemon in /run/daemons/*; do [[ -f $daemon ]] || continue daemon=${daemon##*/} - in_array "$daemon" "${DAEMONS[@]}" || stop_daemon "$daemon" + ck_autostart "$daemon" && stop_daemon "$daemon" done # Shutdown daemons in reverse order -- 1.7.1
This allows splash systems etc. to get a list of daemons to be stopped by simply overriding stop_daemon(). --- functions | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diff --git a/functions b/functions index 7054f60..9cc9cc6 100644 --- a/functions +++ b/functions @@ -279,10 +279,10 @@ add_omit_pids() { omit_pids+=( $@ ) } - -kill_everything() { - # $1 = where we are being called from. - # This is used to determine which hooks to run. +# Stop all daemons +# This function should *never* ever perform any other actions beside calling stop_daemon()! +# It might be used by a splash system etc. to count or get a list of daemons to be stopped. +stop_all_daemons() { # Find daemons NOT in the DAEMONS array. Shut these down first local daemon for daemon in /run/daemons/*; do @@ -297,6 +297,15 @@ kill_everything() { [[ ${DAEMONS[i]} = '!'* ]] && continue ck_daemon ${DAEMONS[i]#@} || stop_daemon ${DAEMONS[i]#@} done +} + +kill_everything() { + # $1 = where we are being called from. + # This is used to determine which hooks to run. + + run_hook "$1_prestopdaemons" + + stop_all_daemons run_hook "$1_prekillall" -- 1.7.1
Kurt J. Bosch, 2011-07-03 22:31:
This allows splash systems etc. to get a list of daemons to be stopped by simply overriding stop_daemon(). --- functions | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/functions b/functions index 7054f60..9cc9cc6 100644 --- a/functions +++ b/functions @@ -279,10 +279,10 @@ add_omit_pids() { omit_pids+=( $@ ) }
- -kill_everything() { - # $1 = where we are being called from. - # This is used to determine which hooks to run. +# Stop all daemons +# This function should *never* ever perform any other actions beside calling stop_daemon()! +# It might be used by a splash system etc. to count or get a list of daemons to be stopped. +stop_all_daemons() { # Find daemons NOT in the DAEMONS array. Shut these down first local daemon for daemon in /run/daemons/*; do @@ -297,6 +297,15 @@ kill_everything() { [[ ${DAEMONS[i]} = '!'* ]]&& continue ck_daemon ${DAEMONS[i]#@} || stop_daemon ${DAEMONS[i]#@} done +} + +kill_everything() { + # $1 = where we are being called from. + # This is used to determine which hooks to run. + + run_hook "$1_prestopdaemons" + + stop_all_daemons
run_hook "$1_prekillall"
Squashed this into [PATCH 06/13] rc.sysinit/functions: Refactor kill_everything/fsck_all/mount_all and dropped the new hook because shutdown_start should be enough for now. -- Kurt
killall5 returns 2 if it didn't find any processes to send to. Using this avoids sleeping longer than needed. This saves another up to six seconds of reboot/shutdown/go-single time. --- functions | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/functions b/functions index 9cc9cc6..71d0312 100644 --- a/functions +++ b/functions @@ -310,14 +310,25 @@ kill_everything() { run_hook "$1_prekillall" # Terminate all processes + # and wait until timeout or killall5 reports all done + # Unfortunately killall5 does not support the 0 signal, so just + # use SIGCONT for checking (which should be ignored). stat_busy "Sending SIGTERM To Processes" + local i killall5 -15 ${omit_pids[@]/#/-o } &>/dev/null - sleep 5 + for (( i=0; i<20 && $?!=2; i++ )); do + sleep .25 # 1/4 second + killall5 -18 ${omit_pids[@]/#/-o } &>/dev/null + done stat_done stat_busy "Sending SIGKILL To Processes" + local i killall5 -9 ${omit_pids[@]/#/-o } &>/dev/null - sleep 1 + for (( i=0; i<4 && $?!=2; i++ )); do + sleep .25 # 1/4 second + killall5 -18 ${omit_pids[@]/#/-o } &>/dev/null + done stat_done run_hook "$1_postkillall" -- 1.7.1
We set $PATH in functions now, so use it. --- netfs | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/netfs b/netfs index 2bcec6c..7ca59ab 100755 --- a/netfs +++ b/netfs @@ -9,9 +9,9 @@ rc=0 case "$1" in start) stat_busy "Mounting Network Filesystems" - /bin/mount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs + mount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs rc=$? - /bin/mount -a -O _netdev + mount -a -O _netdev if ((rc + $? > 0)); then stat_fail else @@ -21,9 +21,9 @@ case "$1" in ;; stop) stat_busy "Unmounting Network Filesystems" - /bin/umount -a -O _netdev + umount -a -O _netdev rc=$? - /bin/umount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs + umount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs if ((rc + $? > 0)); then stat_fail else -- 1.7.1
--- netfs | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/netfs b/netfs index 7ca59ab..c2fcfc9 100755 --- a/netfs +++ b/netfs @@ -4,15 +4,13 @@ . /etc/rc.conf . /etc/rc.d/functions -rc=0 - case "$1" in start) stat_busy "Mounting Network Filesystems" mount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs rc=$? mount -a -O _netdev - if ((rc + $? > 0)); then + if (( rc || $? )); then stat_fail else add_daemon netfs @@ -24,7 +22,7 @@ case "$1" in umount -a -O _netdev rc=$? umount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs - if ((rc + $? > 0)); then + if (( rc || $? )); then stat_fail else rm_daemon netfs -- 1.7.1
Maybe someone wants to abort suspend to disk/ram or something if umount fails. --- netfs | 19 +++++++------------ 1 files changed, 7 insertions(+), 12 deletions(-) diff --git a/netfs b/netfs index c2fcfc9..85c08be 100755 --- a/netfs +++ b/netfs @@ -10,24 +10,18 @@ case "$1" in mount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs rc=$? mount -a -O _netdev - if (( rc || $? )); then - stat_fail - else - add_daemon netfs - stat_done - fi + (( rc || $? )) && stat_die + add_daemon netfs + stat_done ;; stop) stat_busy "Unmounting Network Filesystems" umount -a -O _netdev rc=$? umount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs - if (( rc || $? )); then - stat_fail - else - rm_daemon netfs - stat_done - fi + (( rc || $? )) && stat_die + rm_daemon netfs + stat_done ;; restart) $0 stop @@ -36,6 +30,7 @@ case "$1" in ;; *) echo "usage: $0 {start|stop|restart}" + exit 1 esac # vim: set ts=2 noet: -- 1.7.1
Currently $NETFS is used only for fsck and mount in rc.sysinit. Since we moved it into functions, we can use it in netfs too. functions: * Move 'nosysfs' from $NETFS into the mount -a type list because thats obviously the only meaningfull place. * Add 'nofuse.glusterfs' to $NETFS to match the lists in netfs. * Remove all 'no'-prefixes from $NETFS to make it more useful and readable. * Add 'no'-prefixes to fsck and mount -a commands by parameter substitution. netfs: * Instead of the literals use $NETFS from functions which contains the same types now --- functions | 6 +++--- netfs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/functions b/functions index d6715b0..73ea62f 100644 --- a/functions +++ b/functions @@ -397,11 +397,11 @@ read_crypttab() { # Filesystem functions # These can be overridden for customizations like shutdown/loop-fsck. -NETFS="nonfs,nonfs4,nosmbfs,nocifs,nocodafs,noncpfs,nosysfs,noshfs,nofuse,nofuseblk,noglusterfs,nodavfs" +NETFS="nfs,nfs4,smbfs,cifs,codafs,ncpfs,shfs,fuse,fuseblk,glusterfs,davfs,fuse.glusterfs" # Check local filesystems fsck_all() { - fsck -A -T -C$FSCK_FD -a -t "$NETFS,noopts=_netdev" $FORCEFSCK + fsck -A -T -C$FSCK_FD -a -t "no${NETFS//,/,no},noopts=_netdev" $FORCEFSCK return $? } @@ -441,7 +441,7 @@ fsck_reboot() { } mount_all() { - mount -a -t "$NETFS" -O no_netdev + mount -a -t "nosysfs,no${NETFS//,/,no}" -O no_netdev } bootlogd_stop() { diff --git a/netfs b/netfs index 85c08be..3948a57 100755 --- a/netfs +++ b/netfs @@ -7,7 +7,7 @@ case "$1" in start) stat_busy "Mounting Network Filesystems" - mount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs + mount -a -t "$NETFS" rc=$? mount -a -O _netdev (( rc || $? )) && stat_die @@ -18,7 +18,7 @@ case "$1" in stat_busy "Unmounting Network Filesystems" umount -a -O _netdev rc=$? - umount -a -t nfs,nfs4,smbfs,codafs,ncpfs,cifs,shfs,glusterfs,fuse,fuseblk,fuse.glusterfs,davfs + umount -a -t "$NETFS" (( rc || $? )) && stat_die rm_daemon netfs stat_done -- 1.7.1
Current behaviour: a) /var/run is a symlink to /run: Conditional result is 'false' and thus the symlink won't be created at all. b) /var/run is a directory: Conditional result is always 'true' because any symlink was removed when cleaning /var/run. So just unconditionally remove /var/run/daemons and create a new symlink to /run/daemons. This is possible without doing any harm since it shouldn't be in use at this point anyway. --- rc.sysinit | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 7a12d1c..3c3039a 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -231,12 +231,10 @@ RANDOM_SEED=/var/lib/misc/random-seed cp $RANDOM_SEED /dev/urandom stat_busy "Removing Leftover Files" - rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* &>/dev/null + rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* /var/run/daemons &>/dev/null [[ ! -L /var/lock ]] && rm -rf /var/lock/* [[ ! -L /var/run && -d /var/run ]] && find /var/run/ \! -type d -delete - [[ ! -L /var/run && ! -L /var/run/daemons ]] && - rm -rf /var/run/daemons && - ln -s /run/daemons /var/run/daemons + ln -s /run/daemons /var/run/daemons install -Tm 0664 -o root -g utmp <(:) /var/run/utmp # Keep {x,k,g}dm happy with xorg mkdir -m 1777 /tmp/.{X11,ICE}-unix -- 1.7.1
There are only two possible situations: a) /var/run is a symlink to /run: Conditional result is always 'false' even without checking /var/run/daemons (which doesn't exist). b) /var/run is a directory: Conditional result is always 'true' because any symlink was removed when cleaning /var/run. So following changes can be made: * /var/run/daemons can be removed unconditionally because a symlink doesn't survive cleaning of /var/run anyway. * The check whether /var/run/daemons is a symlink can be dropped because it has actually no effect. Furthermore we can refactor to use the same conditional used for cleaning /var/run because we can't create the symlink if /var/run is not a directory. --- rc.sysinit | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 7a12d1c..5a5596d 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -231,12 +231,12 @@ RANDOM_SEED=/var/lib/misc/random-seed cp $RANDOM_SEED /dev/urandom stat_busy "Removing Leftover Files" - rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* &>/dev/null + rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* /var/run/daemons &>/dev/null [[ ! -L /var/lock ]] && rm -rf /var/lock/* - [[ ! -L /var/run && -d /var/run ]] && find /var/run/ \! -type d -delete - [[ ! -L /var/run && ! -L /var/run/daemons ]] && - rm -rf /var/run/daemons && + if [[ ! -L /var/run && -d /var/run ]]; then + find /var/run/ \! -type d -delete ln -s /run/daemons /var/run/daemons + fi install -Tm 0664 -o root -g utmp <(:) /var/run/utmp # Keep {x,k,g}dm happy with xorg mkdir -m 1777 /tmp/.{X11,ICE}-unix -- 1.7.1
Instead of guessing about symlinks, use stat to check whether the filesystem refered to is actually a tmpfs. Then always clean up if it isn't. --- rc.sysinit | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 3c3039a..85fdd3b 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -232,8 +232,8 @@ RANDOM_SEED=/var/lib/misc/random-seed stat_busy "Removing Leftover Files" rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* /var/run/daemons &>/dev/null - [[ ! -L /var/lock ]] && rm -rf /var/lock/* - [[ ! -L /var/run && -d /var/run ]] && find /var/run/ \! -type d -delete + [[ -d /var/lock && $(stat -f -c %T -L /var/lock) != tmpfs ]] && rm -rf /var/lock/* + [[ -d /var/run && $(stat -f -c %T -L /var/run) != tmpfs ]] && find /var/run/ \! -type d -delete ln -s /run/daemons /var/run/daemons install -Tm 0664 -o root -g utmp <(:) /var/run/utmp # Keep {x,k,g}dm happy with xorg -- 1.7.1
Instead of guessing about symlinks, use stat to check whether the filesystem refered to is actually a tmpfs. Then always clean up if it isn't. --- rc.sysinit | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rc.sysinit b/rc.sysinit index 5a5596d..4a39212 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -232,8 +232,8 @@ RANDOM_SEED=/var/lib/misc/random-seed stat_busy "Removing Leftover Files" rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.* /var/run/daemons &>/dev/null - [[ ! -L /var/lock ]] && rm -rf /var/lock/* - if [[ ! -L /var/run && -d /var/run ]]; then + [[ -d /var/lock && $(stat -f -c %T -L /var/lock) != tmpfs ]] && rm -rf /var/lock/* + if [[ -d /var/run && $(stat -f -c %T -L /var/run) != tmpfs ]]; then find /var/run/ \! -type d -delete ln -s /run/daemons /var/run/daemons fi -- 1.7.1
Hi Kurt, I'm just reviewing this. Before I get started, could I ask you to add a few more details to your commit messages? Many things that look obvious to us now might not be obvious to future contributors, so I would prefer too many rather than to few comments. What I have in mind: On Sun, Jul 3, 2011 at 10:31 PM, Kurt J. Bosch <kjb-temp-2009@alpenjodel.de> wrote:
Kurt J. Bosch (13): functions/rc.single: Clean up whitespace
That's ok.
rc.sysinit: Fix stat_busy block indentation
A sentence explaining the "policy" would be nice: "Align stat_{fail,done} with stat_busy".
functions: Get rid of superfluous braces in udevd_modprobe()
Why are they superfluous? This has been pointed out on the list, and it is pretty basic, but I prefer if these kind of things are pointed out explicitly.
functions: Add missing quotes in mount_all()
Why are they needed? It is nice to know the difference between "this is the right way to do it, even if it does not fix a bug" and a bug fix.
functions/rc.multi: Strip paths from binaries rc.sysinit/functions: Refactor kill_everything/fsck_all/mount_all
Those are good.
rc.sysinit: Declare $FORCEFSCK read-only to prevent custom hooks from messing
Fine I guess, but it would be better if you split the summary and justification in two lines: Declare $FORCEFSCK read-only This prevents <name of hooks> from overwriting the value.
functions/rc.sysinit: Refactor fsck-redirection to prevent breakage
Good comments. Question: Is it necessary to declare the empty variables?
functions: Sanitize status() behaviour to make it more intuitive
Good comments. I agree with returning the error code. Not sure about the redirection. If you have a usecase (not the one below), then maybe.
rc.sysinit: Simplify setting hostname by using status() even with redirection now
I don't think this works. Before this patch the status encapsulates the writing to /proc, after this patch it only encapsulates the echo command, so in case we cannot write to /proc the status message does not behave as intended.
functions: Deprecate in_array(), Add replacement is_in_array()
I agree with changing to use ck_daemon, probably about the deprecation too, not sure about adding replacement function without a user though.
functions: Add stop_all_daemons() and related *_prestopdaemons hook functions: Speed up reboot/shutdown by recognizing killall5 exit code 2
Good comments, I'll have to look into the killall5 stuff before deciding though. Cheers, Tom
Tom Gundersen, 2011-07-09 13:24:
Hi Kurt,
I'm just reviewing this. Before I get started, could I ask you to add a few more details to your commit messages? Many things that look obvious to us now might not be obvious to future contributors, so I would prefer too many rather than to few comments.
What I have in mind:
On Sun, Jul 3, 2011 at 10:31 PM, Kurt J. Bosch <kjb-temp-2009@alpenjodel.de> wrote:
Kurt J. Bosch (13): functions/rc.single: Clean up whitespace
That's ok.
rc.sysinit: Fix stat_busy block indentation
A sentence explaining the "policy" would be nice: "Align stat_{fail,done} with stat_busy".
functions: Get rid of superfluous braces in udevd_modprobe()
Why are they superfluous? This has been pointed out on the list, and it is pretty basic, but I prefer if these kind of things are pointed out explicitly.
functions: Add missing quotes in mount_all()
Why are they needed? It is nice to know the difference between "this is the right way to do it, even if it does not fix a bug" and a bug fix.
functions/rc.multi: Strip paths from binaries rc.sysinit/functions: Refactor kill_everything/fsck_all/mount_all
Those are good.
rc.sysinit: Declare $FORCEFSCK read-only to prevent custom hooks from messing
Fine I guess, but it would be better if you split the summary and justification in two lines:
Declare $FORCEFSCK read-only
This prevents<name of hooks> from overwriting the value.
functions/rc.sysinit: Refactor fsck-redirection to prevent breakage
Good comments. Question: Is it necessary to declare the empty variables?
functions: Sanitize status() behaviour to make it more intuitive
Good comments. I agree with returning the error code. Not sure about the redirection. If you have a usecase (not the one below), then maybe.
rc.sysinit: Simplify setting hostname by using status() even with redirection now
I don't think this works. Before this patch the status encapsulates the writing to /proc, after this patch it only encapsulates the echo command, so in case we cannot write to /proc the status message does not behave as intended.
functions: Deprecate in_array(), Add replacement is_in_array()
I agree with changing to use ck_daemon, probably about the deprecation too, not sure about adding replacement function without a user though.
functions: Add stop_all_daemons() and related *_prestopdaemons hook functions: Speed up reboot/shutdown by recognizing killall5 exit code 2
Good comments, I'll have to look into the killall5 stuff before deciding though.
Cheers,
Tom
Rebased again as suggested. Please have a look at the new thread as this one is a bit chaotic meanwhile. -- Kurt
participants (2)
-
Kurt J. Bosch
-
Tom Gundersen