zur Übersicht: Linux: meine Software und Konfigurationstipps

Anleitung zur Einrichtung einer Servicepartition für den automatischen Dateisystemcheck

29.11.2005, Hauke Laging, mail@hauke-laging.de

Dieses Script gehört zu diesem Vorschlag

Feedback

Wenn jemand dieses Script benutzt, würde ich mich über einen kurzen Hinweis darauf freuen.

Versionen

Version Veröffentlichungsdatum wesentliche Änderungen
1.1 29.11.2005
  • Benutzung einer Konfigurationsdatei

  • fsck nur, wenn mount-Versuch scheitert

  • Statistik über die Handhabung der einzelnen Volumes

  • Prüfung (über die UUID des Root-Volumes), ob das Script für dieses System konfiguriert wurde

  • Aufrämen beim Programmende

1.0 14.08.2005
  • erste Version

Ziel

Durch die zweifache Installation einer Linuxdistribution soll die Lösung von Problemen, die das Booten des Systems verhindern, wesentlich vereinfacht werden. Die Zielgruppe dieser Maßnahme sind im wesentlichen die technisch eher unbedarften Anwender, die ansonsten vor ernsten, ohne persönliche Unterstützung oder Recherche in Handbüchern o.ä. kaum lösbaren Problemen stehen. Für versierte Anwender steht die Bequemlichkeit im Vordergrund.

Diese Anleitung erfasst nur Fehler in den Dateisystemen, die wohl häufigste Ursache für nicht regulär bootende Linuxrechner.

Realisierung

Die Umsetzung besteht aus der zweiten Installation der Distribution, gerne in der einfachsten möglichen Variante; lediglich die Hilfsprogramme für alle verwendeten Dateisysteme sowie ein paar Standardtools (grep) und die verwendete Shell (hier: bash) werden natürlich benötigt. Diese Servicepartition wird dann so konfiguriert, dass sie - automatisch oder nach Rückfrage - diejenigen Aktionen durchführt, die die typischen Probleme lösen. Diesen Zweck erfüllt ein Script (ggf. auch mehrere), das aus der entsprechenden Startdatei der Distribution heraus aufgerufen wird (bei SuSE etwa /etc/init.d/boot.local).

Für dieses Script ist der Zugriff auf die Festplatte(n) zwar ausreichend, aber für die Behebung anderer Probleme ist es hilfreich, zumindest die Netzwerkanbindung einzurichten. Sinnvoll, wenn man jemanden kennt, der helfen kann, sind auch die Installation des SSH-Dämons und die Konfiguration des Internetzugangs. Der Internetzugang und die Firewall sollten dabei so eingestellt sein, dass jemand von außen sich einloggen kann. Das alles sollte man vorher mal testen... :-) Um Risiken zu minimieren, kann man für die Servicepartition zwei Bootloadereinträge vorsehen, einen mit und einen ohne Netzwerk (Runlevel 2 und 3), und außerdem die automatische Interneteinwahl verhindern.

Wenn der Anwender beim Booten Probleme hat, startet er den Rechner neu und wählt im Bootmanager die Servicepartition aus.

Das folgende Script versucht die Rootpartition des Hauptsystems zu mounten. Im Fehlerfall wird das Dateisystem repariert. Anschließend werden die passenden fstab-Einträge des Hauptsystems abgearbeitet.

Benutzung des Scripts

Das Script wird über die Datei /etc/linuxrec-fsck.conf konfiguriert. Wenn es diese Datei beim Start nicht findet, legt es eine Schablone an, die dann bearbeitet werden kann. In dieser Datei können auch weitere Variablen vorbelegt werden (siehe Script).

To Do

Geplante Verbesserungen:

Download

  • die untenstehende Datei zum Download
  • die OpenPGP-Signatur

  • #!/bin/bash
    # This software is licenced to you under the Gnu General Puclic License (GPL) 
    # version 2 of the License, or (at your option) any later version.
    # See http://www.gnu.org/
    
    version=1.1
    
    # 1.1, 2005-11-28, Hauke Laging
    #	- check UUID in config file in order to make sure the script has been configured for this system
    #	- bug fix: set mount_ok=no before trying to mount
    #	- exit code 4 added for config file errors
    #	- check for the availability of necessary programs
    #	- try to mount a file system before checking
    #	- cleanup on every kind of exit
    #	- bug fix: $force_this_fsck must be reset for each entry
    #	- report at the end which volumes have been checked
    # version 1.0, 2005-08-14, Hauke Laging, mail@hauke-laging.de, http://www.hauke-laging.de/
    
    # to do
    # - support more file systems (reiser4, xfs)
    
    # DESCRIPTION
    # This script is intended to be called by the start scripts of a second Linux installation 
    # in order to fix file system errors within the main installation. This allows even users 
    # with no technical knowledge to get their system running again by selecting the right 
    # entry in their boot manager menu. It is necessary that this script has been correctly 
    # configured before by its administrator. It checks if that has been done before action.
    
    # USAGE
    # This script does not use command line arguments. For the possible contents of the 
    # configuration file see the lines following "# VARIABLE DEFAULTS" in this script and 
    # the variable explanations after the line "# variables". If there is no configuration file 
    # this script creates a template so just run it.
    
    # Licence and warning
    # This script is licenced to you under the newest official version of the 
    # GNU Public Licence (GPL) at the date of release. This basically means that 
    # you are free to use, modify and distribute this program at no cost.
    # This program probably contains bugs despite testing which may damage your 
    # data though this is improbable. Don't use it (or install it for others) if 
    # you neither can check this code yourself nor can have somebody you trust 
    # do this for you nor want to take this risk. I cannot help you if you run 
    # into problems.
    
    # requirements
    # All necessary kernel modules have to be loaded (e.g. file systems, LVM).
    # This is a critical requirement when upgrading the main Linux installation 
    # and not upgrading the service installtation either.
    # Programs (all in $PATH): awk, e2fsck, reiserfsck, mktemp
    # For all features: blkid
    
    # restrictions
    # supported file systems: ext2, ext3, reiserfs
    # The pseudo type "auto" is not supported!
    # "Must reboot" exit codes of file system check programs are not considered because 
    # this script is intended to be run during a Linux boot after which the system 
    # is rebooted anyway.
    # The mount options loop and encryption are not supported yet.
    
    # hint for testing and modifying this script
    # All configuration variables can be taken from the environment. This makes 
    # it easy to test and modify this script within a Linux installation 
    # different from the one it is intended to be run from finally. Simply 
    # write a small wrapper script which exports the variables you want to 
    # modify and call the script from that wrapper script then. Thus you can 
    # simply copy a modified version of the script to the other Linux installation 
    # without having to care about the overwritten variable values.
    #
    # This script was written and tested under Novell/SuSE Linux 9.3.
    
    # exit codes
    # 0: all run fsck processes were successful (no statement about skipped entries!)
    # 1: internal error (e.g. a bug)
    # 3: At least one fsck process returned with an error or not even the root partition could be mounted
    # 4: config file error
    # 5: necessary program unavailable
    # 6: aborted by user request
    # 7: forced reboot after fsck of the root partition
    
    
    # variables
    # # hard coded in the script
    # config_file: path
    # # predefined (can be supplied by the environment)
    # rootpartition: the device
    # root_fs_type: ext2 | ext3 | reiserfs
    # force_repair: yes | no - try to repair the file system even if that is dangerous (--rebuild-tree)
    # root_fs_mount_point: where to mount the root partition
    # check_all_fs: yes | no - check even file systems with noauto option or check value 0
    # stdin: device file
    # ask_for_every_volume: yes | no - if set to yes, every file system check has to be confirmed
    # mount_root_fs: yes | no
    # dont_modify_stdio: yes | no - if set to yes the file descriptors 0, 1 and 2 are not changed; mind setting $stdin!
    # # run time
    # mount_rc: int
    # mount_ok: yes | no
    # fsck_success: yes | no
    # fsck_rc: int
    # device: path
    # mount_point: path
    # filesystem: string
    # mount_options: string
    # dump: int
    # check_fs: int
    # tmp: mix
    # answer_ok: yes | no
    # answer: string
    # skipped_entry: yes | no
    # force_this_fsck: yes | no
    # all_fsck_ok: yes | no
    # vars_to_be_set_in_cf: array of names of variables which MUST be set in the config file
    # uuid: UUID of the root partition
    # root_volume_installation: device name of the root partition of the running system, taken from /proc/cmdline
    # import_successful: yes | no
    # necessary_programs: array of the names of the needed programs
    # configured_uuid: this is the UUID stored in the config file
    # this_fs_is_ok: yes | no
    # non_rootfs_mount_point: path
    # uuid_check: yes | no : skip check of needed program is unavailable
    # uuid_show: string
    # clean_volumes: array of device names - those volumes which could be mounted without being checked
    # skipped_volumes: array of device names - those volumes which have not been tried to be mounted
    # simple_check_volumes: array of device names - e2fsck and reiserfsck --fix-fixable
    # complex_check_volumes: array of device names - reiserfsck --rebuild-tree
    # failed_check_volumes: array of device names
    # must_reboot: yes | no
    # i: int
    
    set -a # export new variables and functions
    
    cleanup () {
    	# umount non root fs and remove tmp directory
    	umount "$non_rootfs_mount_point" &>/dev/null
    	rmdir "$non_rootfs_mount_point"
    	if [ "$mount_ok" = yes -a "$mount_root_fs" = no ]
    		then
    		echo "Trying to umount the root file system..."
    		umount "$root_fs_mount_point" || echo "umount failed."
    	fi
    } # cleanup ()
    
    reboot_rootfs () {
    	tmp=
    	type init &>/dev/null && tmp=init
    	type telinit &>/dev/null && tmp=telinit
    	echo "The root file system has been repaired but the system must reboot" >&2
    	echo "before the file system can be mounted."
    	echo
    	if [ -n "$tmp" ]
    		then
    		echo "Thus the system is rebooted now by the command '$tmp 6'. If this does"
    		echo "not work you MUST reboot yourself NOW!"
    		$tmp 6
    	else
    		echo "Due to strange circumstances this script cannot reboot this system"
    		echo "thus you MUST reboot yourself NOW!"
    	fi
    	exit 7
    }
    
    echo
    echo "ATTENTION:"
    echo "This script is going to modify your file systems!"
    echo "It will not do this directly but with the help of the respective"
    echo "fsck program. Thus the risk of damaging your data is small but"
    echo "it is definitely there! This software has been written with caution"
    echo "and it has been testet but it probably does contain bugs."
    echo
    echo "If you are sure that you want to use this software AT YOUR OWN RISK"
    echo "then enter \"yes\" (without the \"\"). Otherwise this program will terminate."
    echo "This is a shell script. You are free to check the source code yourself."
    echo
    echo -n "Do you want to use this script (see above for correct answer)? "
    read tmp
    if [ "$tmp" != yes ]
    	then
    	echo "This program aborts now as you have requested."
    	exit 6
    fi
    echo
    
    trap cleanup EXIT
    
    config_file=/etc/linuxrec-fsck.conf
    all_fsck_ok=yes
    must_reboot=no
    declare -a clean_volumes simple_check_volumes complex_check_volumes skipped_volumes
    necessary_programs=(awk e2fsck reiserfsck mktemp)
    for tmp in ${necessary_programs[@]}
    	do
    	if ! type "${tmp}" &>/dev/null
    		then
    		echo "The necessary program $tmp is unavailable; aborting." >&2
    		exit 5
    	fi
    done
    type blkid &>/dev/null && uuid_check=yes || uuid_check=no
    root_volume_installation=$(awk '{for(i=1;i<=NF;i++){if($i~"^root=") {print substr($i,6);exit}}}' < /proc/cmdline)
    test $uuid_check = yes &&  uuid=$(blkid -s UUID $root_volume_installation | awk '{uuid=substr($2,7);uuid_len=length(uuid);print substr(uuid,1,uuid_len-1)}')
    non_rootfs_mount_point=$(mktemp -d /tmp_mout_point.XXXXXX)
    import_successful=no
    if ! [ -f "$config_file" -a -r "$config_file" ]
    	then
    	echo "config file ('$config_file') missing; aborting." >&2
    	if [ $uuid_check = yes ]
    		then
    		uuid_show=$uuid
    	else
    		uuid_show=unknown
    	fi
    	cat <<EOT
    
    Create the file $config_file with the following content (example values, of course):
    configured_uuid=3d977da1-c28d-4115-9fa6-783521207b2d
    rootpartition=/dev/hda1 # this is the root partition of the main Linux installation, that to be checked
    root_fs_type=ext3 # or ext2 or reiserfs
    root_fs_mount_point=/mnt/linuxroot
    # add any variable defined in the script which you want to override
    # end of file content
    
    
    # The UUID of this system ('$root_volume_installation') is: $uuid_show
    EOT
    	if ! [ -e $config_file ]
    		then
    		echo
    		echo
    		echo "An example configuration is written to the file '$config_file'"
    		echo "but you have to activate it."
    		echo
    		cat <<EOT >"$config_file"
    # If the UUID is unavailable then this script could not determine it and you don't have 
    # to find out because the script could not use tha value anyway. Probably the necessary 
    # software (blkid) is not installed on your system.
    # 
    # Correct the values, uncomment them and add any variables from the script which you want to override.
    #
    # configured_uuid=$uuid_show
    # rootpartition=/dev/hda1 # this is the root partition of the main Linux installation, that to be checked
    # root_fs_type=ext3 # or ext2 or reiserfs
    # root_fs_mount_point=/mnt/linuxroot
    
    EOT
    	fi
    	exit 4
    else
    	. "$config_file"
    fi
    # BEGIN: these have to be set in the config file
    vars_to_be_set_in_cf=(rootpartition root_fs_type root_fs_mount_point)
    for tmp in ${vars_to_be_set_in_cf[@]}
    	do
    	if [ -z "${!tmp}" ]
    		then
    		echo "The variable '$tmp' has neither been set in the environment nor in the config file; aborting." >&2
    		exit 4
    	fi
    done
    #: ${rootpartition:=/dev/hda1}
    #: ${root_fs_type:=ext3}
    #: ${root_fs_mount_point:=/mnt/linuxroot}
    # END: these have to be set in the config file
    
    if ! [ -b "$rootpartition" -a -d "$root_fs_mount_point" -a \( "$root_fs_type" = ext2 -o "$root_fs_type" = ext3 -o "$root_fs_type" = reiserfs \) ]
    	then
    	echo "Invalid values in the configuration file; aborting" >&2
    	exit 4
    fi
    
    if [ $uuid_check = yes ]
    	then
    	if [ -z "$configured_uuid" ]
    		then
    		echo "The variable \$configured_uuid has not been set in the config file; aborting." >&2
    		echo "The UUID of this system is $uuid" >&2
    		exit 4
    	else
    		if [ "$configured_uuid" != "$uuid" ]
    			then
    			echo "The configured UUID ('$configured_uuid') does not match the one of this system ('$uuid'); aborting." >&2
    		fi
    	fi
    else
    	echo "On this system this script cannot validate the configuration by comparing the UUIDs."
    	echo "Continue only if you are sure that the configuration is correct."
    	echo
    	echo "root volume of the main installation (the one to be checked): $rootpartition"
    	echo "root file system (the one on $rootpartition): $root_fs_type"
    	echo "mount point for the root file system: $root_fs_mount_point"
    	echo
    	echo -n "Do you want to continue? (y/n)"
    	read tmp
    	if [ "$tmp" != y ]
    		then
    		echo "This script aborts now as you have requested."
    		exit 6
    	fi
    fi
    
    # VARIABLE DEFAULTS
    : ${force_repair:=yes}
    : ${check_all_fs:=no}
    : ${stdin:=/dev/tty}
    : ${ask_for_every_volume:=no}
    : ${mount_root_fs:=yes}
    : ${dont_modify_stdio:=no}
    
    if [ "$dont_modify_stdio" != yes ]
        then
        exec 0<> $stdin 1>&0 2>&0 # standard input and output is not necessarily the console for boot scripts
    fi
    
    echo "This is the script '$0' which will repair the file systems of " >&2
    echo "the Linux installation on '${rootpartition}'." >&2
    if [ "$ask_for_every_volume" = yes ]
        then
        echo "Press enter to start the script."
        read answer
        echo $'\n'
    fi
    
    shopt -s extglob # allow better case branches
    
    mkdir -p "$root_fs_mount_point" || { echo "error, aborting" >&2; exit 1; }
    fsck_success=yes
    awk -v dev="$rootpartition" -v mp="$root_fs_mount_point" -v mounted=no '{if ($1==dev || $2==mp)mounted="yes"};END {if(mounted=="yes") exit 1}' /proc/mounts ||
    { echo "The root partition ('$rootpartition') is already mounted; terminating..." >&2; exit 1; }
    
    
    
    
    
    # BEGIN: check and mount the root file system
    mount_ok=no
    case "$root_fs_type" in
        ext2|ext3)
            echo "Trying to mount the root file system (on '$rootpartition') at '$root_fs_mount_point'"
            mount -t "$root_fs_type" "$rootpartition" "$root_fs_mount_point";mount_rc=$?
            mount_ok=yes
            clean_volumes[0]="$rootpartition ($root_fs_type)"
            if [ $mount_rc -ne 0 ]
                then
                mount_ok=no
                echo "Mount failed, trying to repair the file system (with e2fsck -f -y)"
                e2fsck -f -y "$rootpartition";fsck_rc=$?
                test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                test $fsck_rc -eq 2 && reboot_rootfs
                test $fsck_success = yes && mount -t "$root_fs_type" "$rootpartition" "$root_fs_mount_point" && mount_ok=yes
                test $mount_ok = yes && { tmp=${#simple_check_volumes[*]};simple_check_volumes[$tmp]="$rootpartition ($root_fs_type)"; }
            fi
        ;;
        reiserfs)
            mount -t "$root_fs_type" "$rootpartition" "$root_fs_mount_point";mount_rc=$?
            mount_ok=yes
            if [ $mount_rc -ne 0 ]
                then
                mount_ok=no
                echo "Mount failed, trying to repair the file system (with reiserfsck --fix-fixable)"
                echo Yes | reiserfsck --fix-fixable "$rootpartition";fsck_rc=$?
                test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                test $fsck_rc -eq 2 && reboot_rootfs
                test $mount_ok = yes && { tmp=${#simple_check_volumes[*]};simple_check_volumes[$tmp]="$rootpartition ($root_fs_type)"; }
                if [ $fsck_rc -eq 4 -a ]
                    then
                    echo "reiserfsck --fix-fixable failed, trying reiserfsck --rebuild-tree"
                    if [ "$force_repair" != yes ]
                        then
                        answer_ok=no
                        while [ $answer_ok = no -a "$ask_for_every_volume" = yes ]
                            do
                            # clear
                            echo "Shall the root partition ${rootpartition} "
                            echo "with file system ${filesystem} be repaired with the option --rebuild-tree? (y/n)"
                            echo "Warning: This is dangerous. Press 'y' only if you know what you are doing "
                            echo " - or if you don't have any other option."
                            read answer < $stdin
                            test "$answer" = y -o "$answer" = Y -o "$answer" = n -o "$answer" = Y && { answer_ok=yes; break; }
                            echo "Wrong answer, please try again"$'\n'$'\n'
                            echo
                            sleep 2
                        done
                        force_this_fsck=no
                        test "$answer" = y -o "$answer" = Y && force_this_fsck=yes
                    fi
                    if [ "$force_repair" = yes -o "$force_this_fsck" = yes ]
                        then
                        force_this_fsck=no
                        echo Yes | reiserfsck --rebuild-tree "$rootpartition";fsck_rc=$?
                        test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                        test $fsck_rc -eq 2 && reboot_rootfs
                        test $mount_ok = yes && { tmp=${#complex_check_volumes[*]};complex_check_volumes[$tmp]="$rootpartition ($root_fs_type)"; }
                    fi
                fi
                test $fsck_success = yes && mount -t "$root_fs_type" "$rootpartition" "$root_fs_mount_point" && mount_ok=yes
            else
                clean_volumes[0]="$rootpartition ($root_fs_type)"
            fi
        ;;
        *)
            mount_ok=no
            all_fsck_ok=no
            echo "unsupported file system '$root_fs_type'" >&2
        ;;
    esac
    # END: check and mount the root file system
    
    if [ $mount_ok = no ]
        then
        all_fsck_ok=no
        echo "The root file system of the main Linux installation ('${rootpartition}') could not be mounted." >&2
        echo "Please consult an Linux expert." >&2
        exit 3
    fi
    echo "The root file system was successfully mounted."
    
    # BEGIN: check all fstab entries
    while read device mount_point filesystem mount_options dump check_fs tmp
        do
        echo
        if [ "$ask_for_every_volume" = yes -a "$skipped_entry" != yes ]
            then
            echo "Press enter to continue with the next volume in fstab."
            read answer < $stdin
            echo $'\n'
        else
            echo "The next entry is processed now."
            sleep 1
        fi
        skipped_entry=no
        if [ "$device" = "" -o "${device:0:1}" = "#" ] # skip empty and comment lines
            then
            echo "Skipping an empty or comment line." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if [ "$filesystem" = swap -o "$filesystem" = proc -o "$filesystem" = devpts -o "$filesystem" = usbdevfs -o "$filesystem" = usbfs -o "$filesystem" = sysfs -o "$filesystem" = subfs -o "$filesystem" = none ] # skip special entries (swap, proc, usbdevfs, none...)
            then
            echo "Skipping special entry ('${filesystem}')." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if ! [ -b "$device" ] # skip lines with invalid device
            then
            echo "Skipping a line with the invalid device '$device'." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if [ "$mount_point" = / -o ${device} = "$rootpartition" ] # skip the already mounted root file system
            then
            echo "Skipping the root file system." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if [ "$check_all_fs" != yes ] && [ "${mount_options//noauto}" != "${mount_options}" -o ${check_fs} -eq 0 ] # skip noauto and "nofsck" lines
            then
            echo "Skipping an entry with noauto option or fsck field 0 ('${device}')." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if [ "${mount_options//loop}" != "${mount_options}" -o "${mount_options//encryption}" != "${mount_options}" ] # skip lines with loop or encryption option
            then
            echo "Skipping an entry with loop or encryption option ('${device}'; not supported yet)." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        if [ "$filesystem" != ext2 -a "$filesystem" != ext3 -a "$filesystem" != reiserfs ] # skip unsupported file system types
            then
            echo "Skipping an entry with unsupported file system ('$device', '$filesystem')." >&2
            skipped_entry=yes
            tmp=${#skipped_volumes[*]};skipped_volumes[$tmp]="$device ($filesystem)"
            continue
        fi
        # try to mount the file system; if successful no fsck is necessary
        this_fs_is_ok=no
        if mount -t "$filesystem" "$device" "$non_rootfs_mount_point" &>/dev/null
        	then
        	echo "The $filesystem file system on $device could be mounted - no check necessary, entry skipped."
        	tmp=${#clean_volumes[*]};clean_volumes[$tmp]="$device ($filesystem)"
        	umount "$non_rootfs_mount_point"
        	skipped_entry=yes
        	continue
        fi
        answer_ok=no
        while [ $answer_ok = no -a "$ask_for_every_volume" = yes ]
            do
            # clear
            echo "Shall the partition ${device} (belonging to '$mount_point') with file system ${filesystem} be repaired? (y/n)"
            read answer < $stdin
            test "$answer" = y -o "$answer" = Y -o "$answer" = n -o "$answer" = Y && { answer_ok=yes; break; }
            echo "Wrong answer, please try again"$'\n'$'\n'
            echo
            sleep 2
        done
        test "$answer" = n -o "$answer" = N -a "$ask_for_every_volume" = yes && continue
        case "$filesystem" in
            ext2|ext3)
                echo "Trying to repair the file system on '$device' (with e2fsck -f -y)"
                e2fsck -f -y "$device";fsck_rc=$?
                test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                test $fsck_rc -eq 2 && must_reboot=yes
                test $fsck_success = yes && { tmp=${#simple_check_volumes[*]};simple_check_volumes[$tmp]="$device ($filesystem)"; }
                test $fsck_success != yes && { tmp=${#failed_check_volumes[*]};failed_check_volumes[$tmp]="$device ($filesystem)"; }
            ;;
            reiserfs)
                echo "Trying to repair the file system on '$device' (with reiserfsck --fix-fixable)"
                echo Yes | reiserfsck --fix-fixable "$device";fsck_rc=$?
                test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                test $fsck_rc -eq 2 && must_reboot=yes
                test $fsck_success = yes && { tmp=${#simple_check_volumes[*]};simple_check_volumes[$tmp]="$device ($filesystem)"; }
                test $fsck_success != yes && { tmp=${#failed_check_volumes[*]};failed_check_volumes[$tmp]="$device ($filesystem)"; }
                if [ $fsck_rc -eq 4 ]
                    then
                    echo "reiserfsck --fix-fixable failed, trying reiserfsck --rebuild-tree"
                    if [ "$force_repair" != yes ]
                        then
                        answer_ok=no
                        while [ $answer_ok = no -a "$ask_for_every_volume" = yes ]
                            do
                            # clear
                            echo "Shall the partition ${device} (belonging to '$mount_point') "
                            echo "with file system ${filesystem} be repaired with the option --rebuild-tree? (y/n)"
                            echo "Warning: This is dangerous. Press 'y' only if you know what you are doing "
                            echo " - or if you don't have any other option."
                            read answer < $stdin
                            test "$answer" = y -o "$answer" = Y -o "$answer" = n -o "$answer" = Y && { answer_ok=yes; break; }
                            echo "Wrong answer, please try again"$'\n'$'\n'
                            echo
                            sleep 2
                        done
                        test "$answer" = y -o "$answer" = Y && force_this_fsck=yes
                    fi
                    if [ "$force_repair" = yes -o "$force_this_fsck" = yes ]
                        then
                        force_this_fsck=no
                        echo Yes | reiserfsck --rebuild-tree "$device";fsck_rc=$?
                        test $fsck_rc -eq 0 -o $fsck_rc -eq 1 -o $fsck_rc -eq 2 && fsck_success=yes || fsck_success=no
                        test $fsck_rc -eq 2 && must_reboot=yes
                        test $fsck_success = yes && { tmp=${#complex_check_volumes[*]};complex_check_volumes[$tmp]="$device ($filesystem)"; }
    	            test $fsck_success != yes && { tmp=${#failed_check_volumes[*]};failed_check_volumes[$tmp]="$device ($filesystem)"; }
                    fi
                fi
            ;;
            *)
                skipped_entry=yes
                echo "Unsupported file system '$root_fs_type' on volume '${device}'; skipped" >&2
                continue
            ;;
        esac
        if [ "$fsck_success" = yes ]
            then
            echo "The file system on volume '${device}' has been successfully repaired."
        else
            echo "The file system on volume '${device}' could not be repaired; please consult a Linux expert."
            all_fsck_ok=no
        fi
        echo
    done < "${root_fs_mount_point}/etc/fstab"
    # END: check all fstab entries
    
    echo
    echo "Results:"
    echo "These volumes were clean:"
    tmp=${#clean_volumes[*]}
    for((i=0;i<tmp;i++))
    	do
    	echo "${clean_volumes[$i]}"
    done
    echo
    echo "These volumes were skipped:"
    tmp=${#skipped_volumes[*]}
    for((i=0;i<tmp;i++))
    	do
    	echo "${skipped_volumes[$i]}"
    done
    echo
    echo "These volumes were corrected by a simple fsck:"
    tmp=${#simple_check_volumes[*]}
    for((i=0;i<tmp;i++))
    	do
    	echo "${simple_check_volumes[$i]}"
    done
    echo
    echo "These volumes were corrected by a complex fsck:"
    tmp=${#complex_check_volumes[*]}
    for((i=0;i<tmp;i++))
    	do
    	echo "${complex_check_volumes[$i]}"
    done
    echo
    echo "These volumes could not be corrected by fsck:"
    tmp=${#failed_check_volumes[*]}
    for((i=0;i<tmp;i++))
    	do
    	echo "${failed_check_volumes[$i]}"
    done
    echo
    
    # information should be enough, don't force reboot
    if [ $must_reboot = yes ]
    	then
    	echo
    	echo "WARNING"
    	echo "At least one of the fsck calles returned with an exit code which"
    	echo "indicates that the system must reboot before that file system"
    	echo "can be used. This script does not force a reboot now because it"
    	echo "trusts in you that you will do so now. You may safely modify"
    	echo "the root partition and everything that is mounted now but don't"
    	echo "mount anything unless you REALLY know what you are doing."
    	echo
    	echo "Press enter to continue..."
    	read tmp
    fi
    
    echo
    echo
    echo "The script '$0' has finished. I hope I could help you, bye."
    if [ "$all_fsck_ok" = yes ]
        then
        exit 0
    else
        exit 3
    fi