[arch-projects] [initscripts] [PATCH 20/20] Catch all errors within status blocks

Dave Reisner d at falconindy.com
Sun Jul 10 15:30:40 EDT 2011


You've got large quantities of non-functional changes in here
(whitespace churn), mixed in with reverts to your previous attempts at
turning everything into a single line. Can we pick a direction and stick
with it? This all seems like a lot of cleverness to accomplish...
well...  I'm not sure. What exactly _does_ this accomplish that we
didn't previously have? If we want to be more fine grained about error
checking as your rationale advertises, then let's do that so we can
report a more detailed error than "[FAIL]".

I'm sure I've mentioned this before, but we value simplicity and
readability in the initscripts. This is crucial code that cannot go foul
because of some bash side effect we haven't considered. I'd rather be a
little more verbose and make this easier to troubleshoot than to have to
worry about write errors on process substitutions triggering magical ERR
trap causing an echo somewhere to claim FAIL.

Yes, I know I'm top posting.

d

On Sun, Jul 10, 2011 at 08:58:39PM +0200, Kurt J. Bosch wrote:
> Rationale:
> Instead of ignoring any errors of all commands but the last within a status
> block it is much better to use trap to catch them and report 'FAIL'. One
> might for example miss the utmp group which is needed to propperly install
> /var/run/utmp.
> This also makes the code a bit more simple and readable.
> 
> Note:
> We enable this explicitely (by calling stat_err_trap) because most daemon
> scriptlets don't work well with this by now. Moreover we don't use 'set -E'
> to avoid breaking/complicating [custom/hook] functions.
> ---
>  functions   |   10 ++++++++++
>  netfs       |   12 ++++--------
>  rc.shutdown |    2 ++
>  rc.single   |    2 ++
>  rc.sysinit  |   59 +++++++++++++++++++++++++++++++++--------------------------
>  5 files changed, 51 insertions(+), 34 deletions(-)
> 
> diff --git a/functions b/functions
> index d1d2947..ac5394c 100644
> --- a/functions
> +++ b/functions
> @@ -125,11 +125,17 @@ stat_bkgd() {
>  	printf "   ${C_OTHER}[${C_BKGD}BKGD${C_OTHER}]${C_CLEAR} "
>  }
>  
> +# Allow to catch any errors and get the exit-code of the last failing command
> +stat_err_trap() {
> +	trap 'STAT_ERR=$?' ERR
> +}
> +
>  stat_busy() {
>  	printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
>  	printf "${SAVE_POSITION}"
>  	deltext
>  	printf "   ${C_OTHER}[${C_BUSY}BUSY${C_OTHER}]${C_CLEAR} "
> +	STAT_ERR=0
>  }
>  
>  stat_append() {
> @@ -139,6 +145,10 @@ stat_append() {
>  }
>  
>  stat_done() {
> +	if (( STAT_ERR )); then
> +		stat_fail
> +		return $STAT_ERR
> +	fi
>  	deltext
>  	printf "   ${C_OTHER}[${C_DONE}DONE${C_OTHER}]${C_CLEAR} \n"
>  }
> diff --git a/netfs b/netfs
> index ea7e4eb..4dc91ef 100755
> --- a/netfs
> +++ b/netfs
> @@ -4,24 +4,20 @@
>  . /etc/rc.conf
>  . /etc/rc.d/functions
>  
> +stat_err_trap
> +
>  case "$1" in
>  	start)
>  		stat_busy "Mounting Network Filesystems"
>  		mount -a -t "$NETFS"
> -		rc=$?
>  		mount -a -O _netdev
> -		(( rc || $? )) && stat_die
> -		add_daemon netfs
> -		stat_done
> +		stat_done && add_daemon netfs || exit 1
>  		;;
>  	stop)
>  		stat_busy "Unmounting Network Filesystems"
>  		umount -a -O _netdev
> -		rc=$?
>  		umount -a -t "$NETFS"
> -		(( rc || $? )) && stat_die
> -		rm_daemon netfs
> -		stat_done
> +		stat_done && rm_daemon netfs || exit 1
>  		;;
>  	restart)
>  		$0 stop
> diff --git a/rc.shutdown b/rc.shutdown
> index ed87eec..db4f12b 100755
> --- a/rc.shutdown
> +++ b/rc.shutdown
> @@ -6,6 +6,8 @@
>  . /etc/rc.conf
>  . /etc/rc.d/functions
>  
> +stat_err_trap
> +
>  run_hook shutdown_start
>  
>  # avoid staircase effect
> diff --git a/rc.single b/rc.single
> index 7a87c72..b5c6e66 100755
> --- a/rc.single
> +++ b/rc.single
> @@ -6,6 +6,8 @@
>  . /etc/rc.conf
>  . /etc/rc.d/functions
>  
> +stat_err_trap
> +
>  run_hook single_start
>  
>  if [[ $PREVLEVEL != N ]]; then
> diff --git a/rc.sysinit b/rc.sysinit
> index 97c16c8..be8eb05 100755
> --- a/rc.sysinit
> +++ b/rc.sysinit
> @@ -6,6 +6,8 @@
>  . /etc/rc.conf
>  . /etc/rc.d/functions
>  
> +stat_err_trap
> +
>  echo " "
>  printhl "Arch Linux\n"
>  printhl "${C_H2}http://www.archlinux.org"
> @@ -14,17 +16,19 @@ printsep
>  run_hook sysinit_start
>  
>  # mount /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm (the api filesystems)
> -mountpoint -q /proc    || mount -n -t proc proc /proc -o nosuid,noexec,nodev
> -mountpoint -q /sys     || mount -n -t sysfs sys /sys -o nosuid,noexec,nodev
> -mountpoint -q /run     || mount -n -t tmpfs run /run -o mode=0755,size=10M,nosuid,nodev
> -mountpoint -q /dev     || mount -n -t devtmpfs udev /dev -o mode=0755,size=10M,nosuid &>/dev/null \
> -	|| mount -n -t tmpfs udev /dev -o mode=0755,size=10M,nosuid
> -mkdir -p -m 1777 /run/lock
> -mkdir -p /dev/{pts,shm}
> -mountpoint -q /dev/pts || mount -n /dev/pts &>/dev/null \
> -	|| mount -n -t devpts devpts /dev/pts -o mode=0620,gid=5,nosuid,noexec
> -mountpoint -q /dev/shm || mount -n /dev/shm &>/dev/null \
> -	|| mount -n -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev
> +stat_busy "Mounting API Filesystems"
> +	mountpoint -q /proc    || mount -n -t proc proc /proc -o nosuid,noexec,nodev
> +	mountpoint -q /sys     || mount -n -t sysfs sys /sys -o nosuid,noexec,nodev
> +	mountpoint -q /run     || mount -n -t tmpfs run /run -o mode=0755,size=10M,nosuid,nodev
> +	mountpoint -q /dev     || mount -n -t devtmpfs udev /dev -o mode=0755,size=10M,nosuid &>/dev/null \
> +		|| mount -n -t tmpfs udev /dev -o mode=0755,size=10M,nosuid
> +	mkdir -p -m 1777 /run/lock
> +	mkdir -p /dev/{pts,shm}
> +	mountpoint -q /dev/pts || mount -n /dev/pts &>/dev/null \
> +		|| mount -n -t devpts devpts /dev/pts -o mode=0620,gid=5,nosuid,noexec
> +	mountpoint -q /dev/shm || mount -n /dev/shm &>/dev/null \
> +		|| mount -n -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev
> +stat_done
>  
>  # remount root ro to allow for fsck later on, we remount now to
>  # make sure nothing can open files rw on root which would block a remount
> @@ -46,7 +50,7 @@ esac
>  if [[ $HWCLOCK_PARAMS ]]; then
>  	stat_busy "Adjusting system time and setting kernel timezone"
>  		# enable rtc access
> -		modprobe -q -a rtc-cmos rtc genrtc
> +		modprobe -q -a rtc-cmos rtc genrtc || :
>  		# If devtmpfs is used, the required RTC device already exists now
>  		# Otherwise, create whatever device is available
>  		if ! [[ -c /dev/rtc || -c /dev/rtc0 ]]; then
> @@ -65,7 +69,8 @@ if [[ $HWCLOCK_PARAMS ]]; then
>  		# is used. If HARDWARECLOCK is not set in rc.conf, the value in
>  		# /var/lib/hwclock/adjfile is used (in this case /var can not be a separate
>  		# partition).
> -	TZ=$TIMEZONE hwclock $HWCLOCK_PARAMS && stat_done || stat_fail
> +		TZ=$TIMEZONE hwclock $HWCLOCK_PARAMS
> +	stat_done
>  fi
>  
>  # Start/trigger UDev, load MODULES and settle UDev
> @@ -89,7 +94,7 @@ activate_vgs
>  # Set up non-root encrypted partition mappings
>  if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then
>  	stat_busy "Unlocking encrypted volumes:"
> -		modprobe -q dm-crypt 2>/dev/null
> +		modprobe -q dm-crypt 2>/dev/null || :
>  		do_unlock() {
>  			# $1 = requested name
>  			# $2 = source device
> @@ -167,8 +172,9 @@ if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then
>  			fi
>  			return $failed
>  		}
> -	crypto_unlocked=0
> -	read_crypttab do_unlock && stat_done || stat_fail
> +		crypto_unlocked=0
> +		read_crypttab do_unlock
> +	stat_done
>  	# Maybe someone has LVM on an encrypted block device
>  	(( crypto_unlocked == 1 )) && activate_vgs
>  fi
> @@ -177,14 +183,13 @@ fi
>  [[ -f /forcefsck || " $(< /proc/cmdline) " =~ [[:blank:]]forcefsck[[:blank:]] ]] && FORCEFSCK="-- -f"
>  declare -r FORCEFSCK
>  run_hook sysinit_prefsck
> +fsckret=0
>  if [[ -x $(type -P fsck) ]]; then
>  	stat_busy "Checking Filesystems"
> -		fsck_all >|${FSCK_OUT:-/dev/stdout} 2>|${FSCK_ERR:-/dev/stdout}
> -	declare -r fsckret=$?
> +		fsck_all >|${FSCK_OUT:-/dev/stdout} 2>|${FSCK_ERR:-/dev/stdout} || fsckret=$?
>  	(( fsckret <= 1 )) && stat_done || stat_fail
> -else
> -	declare -r fsckret=0
>  fi
> +declare -r fsckret
>  run_hook sysinit_postfsck
>  
>  # Single-user login and/or automatic reboot if needed
> @@ -201,7 +206,7 @@ if [[ ! -L /etc/mtab ]]; then
>  		else
>  			cat /proc/mounts >| /etc/mtab
>  		fi
> -	(( $? == 0 )) && stat_done || stat_fail
> +	stat_done
>  fi
>  
>  # now mount all the local filesystems
> @@ -227,7 +232,7 @@ 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/.* /var/run/daemons &>/dev/null
> +	rm -rf /etc/{nologin,shutdownpid} /forcefsck /tmp/* /tmp/.[^.]* /tmp/..?* /var/run/daemons
>  	[[ -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
> @@ -240,13 +245,15 @@ stat_done
>  
>  if [[ $HOSTNAME ]]; then
>  	stat_busy "Setting Hostname: $HOSTNAME"
> -	echo "$HOSTNAME" >| /proc/sys/kernel/hostname && stat_done || stat_fail
> +		echo "$HOSTNAME" >| /proc/sys/kernel/hostname
> +	stat_done
>  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
> +	echo "export LANG=$LOCALE" > /etc/profile.d/locale.sh
> +	chmod 0755 /etc/profile.d/locale.sh
> +stat_done
>  
>  if [[ ${LOCALE,,} =~ utf ]]; then
>  	stat_busy "Setting Consoles to UTF-8 mode"
> @@ -282,7 +289,7 @@ stat_busy "Saving dmesg Log"
>  	else
>  		install -Tm 0644 <( dmesg ) /var/log/dmesg.log
>  	fi
> -(( $? == 0 )) && stat_done || stat_fail
> +stat_done
>  
>  run_hook sysinit_end
>  
> -- 
> 1.7.1
> 


More information about the arch-projects mailing list