home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- ### BEGIN INIT INFO
- # Provides: checkroot
- # Required-Start: mountdevsubfs
- # Required-Stop:
- # Should-Start: keymap hwclockfirst
- # Should-stop:
- # Default-Start: S
- # Default-Stop:
- # Short-Description: Check to root file system.
- ### END INIT INFO
-
- PATH=/lib/init:/sbin:/bin
- FSCK_LOGFILE=/var/log/fsck/checkroot
- [ "$FSCKFIX" ] || FSCKFIX=no
- [ "$SULOGIN" ] || SULOGIN=no
- . /lib/init/vars.sh
-
- . /lib/lsb/init-functions
-
- # Always output fsck progress
- stdin=`readlink /proc/self/fd/0`
- if [ "${stdin#/dev/null}" != "$stdin" ]; then
- exec </dev/console >/dev/console 2>&1
- fi
-
- do_start () {
- #
- # Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to
- # be spawned from this script *before anything else* with a timeout,
- # like sysv does.
- #
- [ "$SULOGIN" = yes ] && sulogin -t 30 $CONSOLE
-
- KERNEL="$(uname -s)"
- MACHINE="$(uname -m)"
-
- #
- # Read /etc/fstab, looking for:
- # 1) The root filesystem, resolving LABEL=*|UUID=* entries to the
- # device node,
- # 2) Swap that is on a md device or a file that may be on a md
- # device,
- # 3) The mount parameters for a devfs filesystem.
- #
-
- exec 9<&0 </etc/fstab
-
- fstabroot=/dev/root
- rootdev=none
- roottype=none
- rootopts=defaults
- rootmode=rw
- rootcheck=no
- swap_on_lv=no
- swap_on_file=no
- devfs=
-
- while read DEV MTPT FSTYPE OPTS DUMP PASS JUNK
- do
- case "$DEV" in
- ""|\#*)
- continue;
- ;;
- /dev/mapper/*)
- [ "$FSTYPE" = "swap" ] && swap_on_lv=yes
- ;;
- /dev/*)
- ;;
- LABEL=*|UUID=*)
- if [ "$MTPT" = "/" ] && which findfs >/dev/null 2>&1
- then
- DEV="$(findfs "$DEV")"
- fi
- ;;
- /*)
- [ "$FSTYPE" = "swap" ] && swap_on_file=yes
- ;;
- *)
- # Devfs definition ?
- if [ "$FSTYPE" = "devfs" ] && [ "$MTPT" = "/dev" ] && mountpoint -q /dev
- then
- devfs="-t $FSTYPE $DEV $MTPT"
- fi
- ;;
- esac
- [ "$MTPT" != "/" ] && continue
- rootdev="$DEV"
- fstabroot="$DEV"
- rootopts="$OPTS"
- roottype="$FSTYPE"
- ( [ "$PASS" != 0 ] && [ "$PASS" != "" ] ) && rootcheck=yes
- ( [ "$FSTYPE" = "nfs" ] || [ "$FSTYPE" = "nfs4" ] ) && rootcheck=no
- case "$OPTS" in
- ro|ro,*|*,ro|*,ro,*)
- rootmode=ro
- ;;
- esac
- done
-
- exec 0<&9 9<&-
-
- #
- # Activate the swap device(s) in /etc/fstab. This needs to be done
- # before fsck, since fsck can be quite memory-hungry.
- #
- ENABLE_SWAP=no
- case "$KERNEL" in
- Linux)
- if [ "$swap_on_lv" = yes ]
- then
- [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on logical volume."
- elif [ "$swap_on_file" = yes ]
- then
- [ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on swapfile."
- else
- ENABLE_SWAP=yes
- fi
- ;;
- *)
- ENABLE_SWAP=yes
- ;;
- esac
- if [ "$ENABLE_SWAP" = yes ]
- then
- if [ "$VERBOSE" = no ]
- then
- log_action_begin_msg "Activating swap"
- swapon -a -e >/dev/null 2>&1
- log_action_end_msg $?
- else
- log_action_msg "Will now activate swap"
- swapon -a -v
- ES=$?
- if [ "$ES" = 0 ]
- then
- log_success_msg "Done activating swap."
- else
- log_failure_msg "Swap activation failed with error code ${ES}."
- fi
- fi
- fi
-
- #
- # Does the root device in /etc/fstab match with the actual device ?
- # If not we try to use the /dev/root alias device, and if that
- # fails we create a temporary node in /dev/shm.
- #
- if [ "$rootcheck" = yes ]
- then
- ddev="$(mountpoint -qx $rootdev)"
- rdev="$(mountpoint -d /)"
- if [ "$ddev" != "$rdev" ] && [ "$ddev" != "4:0" ]
- then
- if [ "$(mountpoint -qx /dev/root)" = "4:0" ]
- then
- rootdev=/dev/root
- else
- if \
- rm -f /dev/shm/root \
- && mknod -m 600 /dev/shm/root b ${rdev%:*} ${rdev#*:} \
- && [ -e /dev/shm/root ]
- then
- rootdev=/dev/shm/root
- else
- rootfatal=yes
- fi
- fi
- fi
- fi
-
- #
- # Bother, said Pooh.
- #
- if [ "$rootfatal" = yes ]
- then
- log_failure_msg "The device node $rootdev for the root filesystem is missing or incorrect
- or there is no entry for the root filesystem listed in /etc/fstab.
- The system is also unable to create a temporary node in /dev/shm.
- This means you have to fix the problem manually."
- log_warning_msg "A maintenance shell will now be started.
- CONTROL-D will terminate this shell and restart the system."
- # Start a single user shell on the console
- if ! sulogin $CONSOLE
- then
- log_failure_msg "Attempt to start maintenance shell failed.
- Will restart in 5 seconds."
- sleep 5
- fi
- [ "$VERBOSE" = no ] || log_action_msg "Will now restart"
- reboot -f
- fi
-
- # See if we're on AC Power
- # If not, we're not gonna run our check
- if which on_ac_power >/dev/null 2>&1 && [ "$rootcheck" = yes ]
- then
- on_ac_power >/dev/null 2>&1
- if [ "$?" -eq 1 ]
- then
- log_warning_msg "On battery power, so skipping file system check."
- rootcheck=no
- fi
- fi
-
- #
- # See if we want to check the root file system.
- #
- FSCKCODE=0
- if [ -f /fastboot ]
- then
- [ "$rootcheck" = yes ] && log_warning_msg "Fast boot enabled, so skipping file system check."
- rootcheck=no
- fi
-
- if [ "$rootcheck" = yes ]
- then
- #
- # Ensure that root is quiescent and read-only before fsck'ing.
- #
- # mount -n -o remount,ro / would be the correct syntax but
- # mount can get confused when there is a "bind" mount defined
- # in fstab that bind-mounts "/" somewhere else.
- #
- # So we use mount -n -o remount,ro $rootdev / but that can
- # fail on older kernels on sparc64/alpha architectures due
- # to a bug in sys_mount().
- #
- # As a compromise we try both.
- #
- if \
- ! mount -n -o remount,ro $rootdev / \
- && ! mount -n -o remount,ro -t dummytype $rootdev / 2>/dev/null \
- && ! mount -n -o remount,ro / 2>/dev/null
- then
- log_failure_msg "Cannot check root file system because it is not mounted read-only."
- rootcheck=no
- fi
- fi
-
- #
- # The actual checking is done here.
- #
- if [ "$rootcheck" = yes ]
- then
- if [ -f /forcefsck ]
- then
- force="-f"
- else
- force=""
- fi
-
- if [ "$FSCKFIX" = yes ]
- then
- fix="-y"
- else
- fix="-a"
- fi
-
- spinner="-C"
- case "$TERM" in
- dumb|network|unknown|"")
- spinner="" ;;
- esac
- # This Linux/s390 special case should go away.
- if [ "${KERNEL}:${MACHINE}" = Linux:s390 ]
- then
- spinner=""
- fi
-
- if [ "$VERBOSE" = no ]
- then
- log_action_begin_msg "Checking root file system"
- logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -t $roottype $rootdev
- FSCKCODE=$?
- if [ "$FSCKCODE" = 0 ]
- then
- log_action_end_msg 0
- else
- log_action_end_msg 1 "code $FSCKCODE"
- fi
- else
- log_action_msg "Will now check root file system"
- logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $roottype $rootdev
- FSCKCODE=$?
- if [ "$FSCKCODE" = 0 ]
- then
- log_success_msg "Done checking root file system.
- A log will be saved in ${FSCK_LOGFILE} if that location is writable."
- else
- log_failure_msg "Root file system check failed with error code ${FSCKCODE}.
- A log is being saved in ${FSCK_LOGFILE} if that location is writable."
- fi
- fi
- fi
-
- #
- # If there was a failure, drop into single-user mode.
- #
- # NOTE: "failure" is defined as exiting with a return code of
- # 4 or larger. A return code of 1 indicates that file system
- # errors were corrected but that the boot may proceed. A return
- # code of 2 or 3 indicates that the system should immediately reboot.
- #
- if [ "$FSCKCODE" -gt 3 ]
- then
- # Surprise! Re-directing from a HERE document (as in "cat << EOF")
- # does not work because the root is currently read-only.
- log_failure_msg "An automatic file system check (fsck) of the root filesystem failed.
- A manual fsck must be performed, then the system restarted.
- The fsck should be performed in maintenance mode with the
- root filesystem mounted in read-only mode."
- log_warning_msg "The root filesystem is currently mounted in read-only mode.
- A maintenance shell will now be started.
- After performing system maintenance, press CONTROL-D
- to terminate the maintenance shell and restart the system."
- # Start a single user shell on the console
- if ! sulogin $CONSOLE
- then
- log_failure_msg "Attempt to start maintenance shell failed.
- Will restart in 5 seconds."
- sleep 5
- fi
- [ "$VERBOSE" = no ] || log_action_msg "Will now restart"
- reboot -f
- elif [ "$FSCKCODE" -gt 1 ]
- then
- log_failure_msg "The file system check corrected errors on the root partition
- but requested that the system be restarted."
- log_warning_msg "The system will be restarted in 5 seconds."
- sleep 5
- [ "$VERBOSE" = no ] || log_action_msg "Will now restart"
- reboot -f
- fi
-
- #
- # Remount root to final mode (rw or ro).
- #
- # See the comments above at the previous "mount -o remount"
- # for an explanation why we try this twice.
- #
- if ! mount -n -o remount,$rootopts,$rootmode $fstabroot / 2>/dev/null
- then
- mount -n -o remount,$rootopts,$rootmode /
- fi
-
- #
- # We only create/modify /etc/mtab if the location where it is
- # stored is writable. If /etc/mtab is a symlink into /proc/
- # then it is not writable.
- #
- INIT_MTAB_FILE=no
- MTAB_PATH="$(readlink -f /etc/mtab || :)"
- case "$MTAB_PATH" in
- /proc/*)
- ;;
- /*)
- if touch "$MTAB_PATH" >/dev/null 2>&1
- then
- :> "$MTAB_PATH"
- rm -f ${MTAB_PATH}~
- INIT_MTAB_FILE=yes
- fi
- ;;
- "")
- [ -L /etc/mtab ] && MTAB_PATH="$(readlink /etc/mtab)"
- if [ "$MTAB_PATH" ]
- then
- log_failure_msg "Cannot initialize ${MTAB_PATH}."
- else
- log_failure_msg "Cannot initialize /etc/mtab."
- fi
- ;;
- *)
- log_failure_msg "Illegal mtab location '${MTAB_PATH}'."
- ;;
- esac
-
- if [ "$INIT_MTAB_FILE" = yes ]
- then
- [ "$roottype" != none ] &&
- mount -f -o $rootopts -t $roottype $fstabroot /
- [ "$devfs" ] && mount -f $devfs
- fi
-
- #
- # Remove /dev/shm/root if we created it.
- #
- rm -f /dev/shm/root
- }
-
- case "$1" in
- start|"")
- do_start
- ;;
- restart|reload|force-reload)
- echo "Error: argument '$1' not supported" >&2
- exit 3
- ;;
- stop)
- # No-op
- ;;
- *)
- echo "Usage: checkroot.sh [start|stop]" >&2
- exit 3
- ;;
- esac
-
- :
-