[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: forced fsck (again?)



-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160

Theodore Tso wrote:
> So ---- for someone who has time, I offer the following challenge.
> Take the above script, and enhance it in the following ways:
> 
> 	* Read a configuration file to see which filesystem(s) to
>           check and to which e-mail the error reports should be sent.

Add support for checking multiple FSes, too.  :-)

> 	* Have the script abort the check if the system appears to be
>           running off of a battery.

Sort of.  Much of this on_ac_power function was stolen from Debian's
powermgmt_base package's on_ac_power script, but it doesn't support
anything other than ACPI.  (It checks the new sysfs power_supply class
first, and the /proc/acpi/ac_adapter/ directory second.)

If the function can't determine if AC power is available, the script
assumes it's on battery, and exits; this is suboptimal for desktops, but
good for laptops that don't have ACPI turned on for whatever reason.

> 	* Have the config file define a time period (say, 30 days),
>           and have the script test to see if the last_mount time is
>           greater than the time interval.  If it is, then it does the
>           check, otherwise it skips it.

Well, this script looks at the last-check time, not the last-mount time.
But close enough.

> With these enhancements, in the laptop case the script could be fired
> off by cron every night at 3am, and if a month has gone by without a
> check, AND the laptop is running off the AC mains, the check happens
> automatically, in the background.

See the attached script (e2check) and sample config file (e2check.conf).
:-)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHlp1nS5vET1Wea5wRA2XkAKC9vPadZzYxbBITFVkSUAntYGOk4QCg4+SZ
QK+2xfdB7wtVF/J152S/P2s=
=lhcS
-----END PGP SIGNATURE-----
#!/bin/sh
#
# e2check

function on_ac_power() {
	local any_known=no

	# try sysfs power class first
	if [ -d /sys/class/power_supply ] ; then
		for psu in /sys/class/power_supply/* ; do
			if [ -r "${psu}/type" ] ; then
				type="`cat "${psu}/type"`"

				# ignore batteries
				[ "${type}" = "Battery" ] && continue

				online="`cat "${psu}/online"`"

				[ "${online}" = 1 ] && return 0
				[ "${online}" = 0 ] && any_known=yes
			fi
		done

		[ "${any_known}" = "yes" ] && return 1
	fi

	# else fall back to AC adapters in /proc
	if [ -d /proc/acpi/ac_adapter ] ; then
		for ac in /proc/acpi/ac_adapter/* ; do
			if [ -r "${ac}/state" ] ; then
				grep -q on-line "${ac}/state" && return 0
				grep -q off-line "${ac}/state" && any_known=yes
			elif [ -r "${ac}/status" ] ; then
				grep -q on-line "${ac}/status" && return 0
				grep -q off-line "${ac}/status" && any_known=yes
			fi
		done

		[ "${any_known}" = "yes" ] && return 1
	fi

	return 255
}

TMPFILE=`mktemp -t e2fsck.log.XXXXXXXXXX`

# be sure to delete the temp file
trap "rm $TMPFILE" EXIT

set -e

# pull in configuration -- don't bother with a parser, just use the shell's
. /etc/e2check.conf

# ensure VGS, VOLUMES, and SNAPSIZES have the same number of items
if [ "${#VGS[ ]}" -ne "${#VOLUMES[ ]}" ] || [ "${#VGS[ ]}" -ne "${#SNAPSIZES[ ]}" ] || \
		[ "${#VGS[ ]}" -ne "${#INTERVALS[ ]}" ] ; then
	echo "Error: Sizes of VGS, VOLUMES, SNAPSIZES, and INTERVALS arrays differ" >&2
	exit 1
fi

# check whether the machine is on AC power: if not, skip the e2fsck
if on_ac_power ; then
	for (( i=0; i<${#VGS[ ]}; i+=1 )) ; do
		VOLUME="${VOLUMES[$i]}"
		VG="${VGS[$i]}"
		SNAPSIZE="${SNAPSIZES[$i]}"
		INTERVAL="${INTERVALS[$i]}"

		# get the last check time plus $INTERVAL days
		dumpe2fs -h "/dev/${VG}/${VOLUME}" | grep 'Last checked:' | \
			sed -e 's/Last checked:[[:space:]]*//' | while read check_date ; do
			check_day=`date --date="${check_date} $INTERVAL days" +"%Y%m%d"`
		done

		# get today's date
		today=`date +"%Y%m%d"`

		# skip LVs that don't need to be checked yet
		[ "$check_day" -gt "$today" ] && continue

		# clear the log file for each LV
		> $TMPFILE

		# use a different start time for each LV
		START="$(date +'%Y%m%d%H%M%S')"

		lvcreate -s -L ${SNAPSIZE} -n "${VOLUME}-snap" "${VG}/${VOLUME}"

		if nice logsave -as $TMPFILE e2fsck -p -C 0 "/dev/${VG}/${VOLUME}-snap" && \
				nice logsave -as $TMPFILE e2fsck -fy -C 0 "/dev/${VG}/${VOLUME}-snap" ; then
			echo 'Background scrubbing succeeded!'
			tune2fs -C 0 -T "${START}" "/dev/${VG}/${VOLUME}"
		else
			echo 'Background scrubbing failed! Reboot to fsck soon!'
			tune2fs -C 16000 -T "19000101" "/dev/${VG}/${VOLUME}"

			if test -n "$EMAIL"; then
				mail -s "E2fsck of /dev/${VG}/${VOLUME} failed!" $EMAIL < $TMPFILE
			fi
		fi

		lvremove -f "${VG}/${VOLUME}-snap"
	done
fi

#!/bin/sh

# Configuration variables:
#  EMAIL
#   address to send failure notifications to (if empty,
#   failure notifications will not be sent)
#  VGS
#   array of volume groups to check
#  VOLUMES
#   array of logical volumes to check, one for each
#   volume group listed in VGS
#  SNAPSIZES
#   size of each LVM snapshot (any string accepted by
#   the -L option to lvcreate is valid), one for each
#   volume group listed in VGS
#  INTERVALS
#   days to wait between checks, one for each volume
#   group listed in VGS

EMAIL='tytso mit edu'

VGS=(closure closure)
VOLUMES=(root home)
SNAPSIZES=(100m 100m)
INTERVALS=(30 30)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]