0. 概述

fsck的运行主要需要解决两个问题:

1、怎么样才能让系统调用fsck?

2、fsck被调用时很多情况下只会打印一些信息,怎么样才能启动完整的磁盘扫描?

1. Upstart 方式 (ubuntu 14.04 32bit)

Upstart的fsck配置概述如下:

1.1 配置fsck启动

  • 1、fstab的pass选项

一个分区如果需要在启动的过程中做磁盘修复,需要把fstab中的pass选项配置成1或者2。这样mountall命令才会对对应分区调用fsck操作;

根分区/pass选项默认为1,在fstab文件中无法更改;

1.2 配置fsck运行参数

在fsck被mountall调用后,并不会对对应分区做完整的扫描。

它需要满足以下任一条件才会启动:
条件1、文件系统被标记出错"dirty";
条件2、需要满足check间隔的时间 或者 mount的次数到达限制;
条件3、使用-f选项调用fsck;

  • 1、force-fsck模式

使能force-fsck模式,会强制对根分区/进行fsck完整扫描。

它的操作有以下特点:
特点1、只会影响根分区/,对其他分区无效;
特点2、根分区/pass选项默认为1,所以fstab中的配置无影响;
特点3、会直接使用-f选项调用fsck,会强行完整扫描,突破check时间、mount次数、错误状态的限制;

有以下几种方式可以进入force-fsck模式:
方式1:在根目录/下创建/forcefsck文件。这种方式可以强制系统在启动时进入1次force-fsck模式,在执行完强制fsck后,系统会自动删除/forcefsck文件;
方式2:在cmdline中加入force-fsck选项。这种方式是永久有效的,每次系统启动时都会使能force-fsck模式;

  • 2、fsck-fix选项

在fsck检查到错误时,怎么样应对修复?

fsck的-a-y对应不同的修复策略:

optdescripts
-aAutomatically repair the filesystem without any questions (use this option with caution). Note that e2fsck supports -a for backward compatibility only. This option is mapped to e2fsck’s -p option that is safe to use, unlike the -a option that some filesystem checkers support.
-yFor some filesystem-specific checkers, the -y option will cause the fs-specific fsck to always attempt to fix any detected filesystem corruption automatically. Sometimes an expert may be able to do better driving the fsck manually. Note that not all filesystem-specific checkers implement this option. In particular fsck.minix and fsck.cramfs do not support the -y option.

fsck默认使用-a选项。
如果"/etc/default/rcS"文件中的变量"$FSCKFIX" = “yes”,fsck使用-y选项。

下面是具体的分析过程。

1.3 mountall.config

在这里插入图片描述

updtart系统启动过程中关于磁盘挂载的流程:init -> /etc/init/mountall.conf -> mountall。首先mountall.conf会响应startup事件根据配置调用mountall程序,mountall会读取 /lib/init/fstab 和 /etc/fstab 里的配置按顺序挂载分区。

  • mountall.conf配置
# mountall - Mount filesystems on boot
#
# This helper mounts filesystems in the correct order as the devices
# and mountpoints become available.

description     "Mount filesystems on boot"

start on startup
stop on starting rcS

expect daemon
task

emits virtual-filesystems
emits local-filesystems
emits remote-filesystems
emits all-swaps
emits filesystem
emits mounting
emits mounted

script

    /* (1) 从"/etc/default/rcS"导入配置  */
    . /etc/default/rcS || true

    /* (2) 如果根目录下有"/forcefsck"文件,设置mountall命令的"--force-fsck"选项 */
    [ -f /forcefsck ] && force_fsck="--force-fsck"      

    /* (3) 如果变量"$FSCKFIX" = "yes",设置mountall命令的"--fsck-fix"选项 */
    [ "$FSCKFIX" = "yes" ] && fsck_fix="--fsck-fix"

    # Doesn't work so well if mountall is responsible for mounting /proc, heh.
    /* (4) 从cmdline中解析出的"$debug_arg"选项 */
    if [ -e /proc/cmdline ]; then
        read line < /proc/cmdline
        for arg in $line; do
            case $arg in
                -q|--quiet|-v|--verbose|--debug)
                    debug_arg=$arg
                    ;;
            esac
        done < /proc/cmdline
    fi
    # set $LANG so that messages appearing in plymouth are translated
    if [ -r /etc/default/locale ]; then
        . /etc/default/locale || true
        export LANG LANGUAGE LC_MESSAGES LC_ALL
    fi

    /* (5) 使用各种选项来调用mountall命令 */
    exec mountall --daemon $force_fsck $fsck_fix $debug_arg
end script

post-stop script
    /* (6) script执行完成后,删除可能存在的"/forcefsck"文件 */
    rm -f /forcefsck 2>dev/null || true
end script

可以看到mountall.conf中有两个配置会影响到fsck的检查:

配置1.1:"/forcefsck"文件。

如果存在"/forcefsck"文件,传递"–force-fsck"选项给mountall命令调用:

如果传递--force-fsckmountall最后会使用-f选项来调用fsck命令对根目录/进行强制磁盘扫描;注意该选项只对根目录/有效,对其他分区无效;

配置1.2:rcS文件中的"$FSCKFIX"配置。

如果"/etc/default/rcS"文件中的变量"$FSCKFIX" = “yes”,传递"–fsck-fix"选项给mountall命令调用:

如果传递--fsck-fixmountall最后会使用-y选项来调用fsck命令;该选项的意思是如果扫描到出错,默认回答yes进行修复;否则使用-a选项来调用fsck命令,错误修复需要用户来回答;

1.4 mountall

关于系统启动过程中的fsck操作,第一步会进入mountall,mountall命令解析各种参数,再根据参数调用fsck

  • mountall命令参数
$ mountall --help
Usage: mountall [OPTION]...
启动时挂载文件系统

Options:
      --daemon                Detach and run in the background
      --force-fsck            Force check of all filesystems
      --fsck-fix              Attempt to fix all fsck errors
      --no-events             Do not emit events after mounting filesystems
      --dev-wait-time=value in seconds (Default is 30 seconds, Legal value between 1second to 2147483647 seconds)
                              In case of (bootwait,timeout): specify the time to wait for device to be detected
  -q, --quiet                 reduce output to errors only
  -v, --verbose               increase output to include informational messages
      --help                  display this help and exit
      --version               output version information and exit

mountall 默认运行在前台且不自动进行控制台分离,请使用 --daemon 参数使其成为守护进程。

Report bugs to <ubuntu-devel@lists.ubuntu.com>
  • mountall命令的实现

在mountall.conf解析完选项后会调用mountall命令,mountall命令中继续实现对fsck相关各项参数的解析和调用。

配置2.1:cmdline中的force-fsck选项。

如果cmdline中存在force-fsck选项,mountall最后会使用-f选项来调用fsck命令对根目录/进行强制磁盘扫描;注意该选项只对根目录/有效,对其他分区无效;

mountall-2.53\src\mountall.c:

main()
{

	/* Check for force-fsck on the kernel command line */
	cmdline = fopen ("/proc/cmdline", "r");
	if (cmdline) {
		char line[4096];

		if (fgets (line, sizeof line, cmdline)) {
			char *tok;

			for (tok = strtok (line, " "); tok;
			     tok = strtok (NULL, " "))
				 /* (1) 根据cmdline中的关键字配置force_fsck参数 */
				if (! strcmp (tok, "force-fsck"))
					force_fsck = 1;
		}

		fclose (cmdline);
	}

}

需要特别注意的是,force-fsck有2个特点:

1、它只对根目录/有效,设置了该选项只会强制扫描根目录,对其他分区无效;
2、它会突破e2fsck中Maximum mount count选项的限制,只要设置了force-fsck选项,无视Maximum mount count选项的配置;

配置2.2:fstab文件中pass选项。

对于没有配置force-fsck选项的场景,需要根据fstab文件中pass选项来决定是否调用fsck命令对对应的分区进行磁盘扫描:

/etc/fstab:

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=a9cee914-ac8e-4f1b-8ef1-7c036b491e63 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=a0a57bb8-ebd8-4e99-a7b8-ba94fea5dc0e none            swap    sw              0       0
/dev/fd0        /media/floppy0  auto    rw,user,noauto,exec,utf8 0       0
/dev/sdb1       /usr/src/work   ext3    defaults                 0       0
UUID=f3221963-db14-477f-913f-5ff3a74f026a /home/zhoulei/data ext4 defaults      0       0

和fsck相关的是最后一个pass选项:

0: 值为0时,永远不检查;
1: 而 / 根目录分区永远都为1。
2: 其它分区从2开始,数字越小越先检查,如果两个分区的数字相同,则同时检查。

注意:根目录/不管fstab中pass选项的配置,根目录分区pass永远都为1;

mountall命令源代码中对fstab选项的解析:

mountall-2.53\src\mountall.c:

main() -> parse_fstab()

void
parse_fstab (const char *filename)
{

    /* (1) fstab中的"pass"选项解析到 mntent->mnt_passno 结构体成员当中
		并且赋值给 mnt->check
	 */
	while ((mntent = getmntent (fstab)) != NULL) {
		Mount *         mnt;
		nih_local char *fsname = NULL;

		mnt = find_mount (mntent->mnt_dir);
		if (mnt && (!mnt->src || strcmp (mnt->src, filename))
		    && strcmp (mntent->mnt_type, "swap")) {
			update_mount (mnt,
				      mntent->mnt_fsname,
				      mntent->mnt_passno != 0,
				      mntent->mnt_type,
				      mntent->mnt_opts);
		} else {
			new_mount (mntent->mnt_dir,
				   mntent->mnt_fsname,
				   mntent->mnt_passno != 0,
				   mntent->mnt_type,
				   mntent->mnt_opts,
				   filename);
		}
	}

	endmntent (fstab);
}

mountall命令源代码中对是否执行fsck的判断:

mountall-2.53\src\mountall.c:

void
run_fsck (Mount *mnt)
{
	nih_local char **args = NULL;
	size_t           args_len = 0;
	int              fds[2];
	int              flags;

	nih_assert (mnt != NULL);

    /* (1) 对于不满足fsck条件的,直接mount完返回 */
	if (mnt->ready) {
		nih_debug ("%s: already ready", MOUNT_NAME (mnt));
		try_mount (mnt, FALSE);
		return;
	/* (1.1) 对于普通分区 mnt->check > 0 时调用fsck
			 对于"/"根分区 force_fsck = 1 时调用fsck
	 */
	} else if (! mnt->check
		   && (! force_fsck || strcmp (mnt->mountpoint, "/"))) {
		nih_debug ("%s: no check required", MOUNT_NAME (mnt));
		mnt->ready = TRUE;
		try_mount (mnt, FALSE);
		return;
	} else if (missing_fsck (mnt)) {
		nih_debug ("%s: no appropriate fsck.* present",
			   MOUNT_NAME (mnt));
		mnt->ready = TRUE;
		try_mount (mnt, FALSE);
		return;
	} else if (mnt->nodev
		   || (! strcmp (mnt->type, "none"))) {
		nih_debug ("%s: no device to check", MOUNT_NAME (mnt));
		mnt->ready = TRUE;
		try_mount (mnt, FALSE);
		return;
	} else if (mnt->mounted && (! has_option (mnt, "ro", TRUE))) {
		nih_debug ("%s: mounted filesystem", MOUNT_NAME (mnt));
		mnt->ready = TRUE;
		try_mount (mnt, FALSE);
		return;
	} else if (mnt->fsck_pid > 0) {
		nih_debug ("%s: already checking", MOUNT_NAME (mnt));
		return;
	} else if (mnt->error > ERROR_BORED) {
		nih_debug ("%s still has uncleared errors", MOUNT_NAME (mnt));
		return;
	}

	nih_info (_("checking %s"), MOUNT_NAME (mnt));

	/* Create a pipe to receive progress indication */
	if (pipe2 (fds, O_CLOEXEC) < 0) {
		nih_fatal ("Unable to create pipe for spawned process: %s",
			   strerror (errno));
		exit (EXIT_ERROR);
	}

	flags = fcntl (fds[1], F_GETFD);
	if ((flags < 0)
	    || (fcntl (fds[1], F_SETFD, flags &~ FD_CLOEXEC) < 0)
	    || (! NIH_SHOULD (nih_io_reopen (NULL, fds[0], NIH_IO_STREAM,
					     (NihIoReader)fsck_reader,
					     NULL, NULL, mnt)))) {
		close (fds[0]);
		close (fds[1]);
		fds[0] = fds[1] = -1;
	}

    /* (2) 对于满足fsck条件的,构造fsck命令的选项 args */
	args = NIH_MUST (nih_str_array_new (NULL));
	NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "fsck"));
	if (fsck_fix || mnt->fsck_fix) {
		NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-y"));
	} else {
		NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-a"));
	}
	if (fds[1] >= 0) {
		nih_local char *arg = NULL;

		arg = NIH_MUST (nih_sprintf (NULL, "-C%d", fds[1]));
		NIH_MUST (nih_str_array_addp (&args, NULL, &args_len, arg));
	}
	if (force_fsck)
		NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-f"));
	NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-t"));
	NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->type));
	NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->device));

	mnt->error = ERROR_NONE;
	/* (2.1) 创建新线程来执行fsck,具体参数配置在args中 */
	mnt->fsck_pid = spawn (mnt, args, FALSE, run_fsck_finished);
	mnt->fsck_progress = -1;

	fsck_update ();

	/* Close writing end, reading end is left open inside the NihIo
	 * structure watching it until the remote end is closed by fsck
	 * finishing.
	 */
	if (fds[1] >= 0)
		close (fds[1]);
}

1.5 fsck

mountall命令的运行的过程中,会根据配置来调用fsck命令:

  • fsck命令参数
$ fsck --help
fsck,来自 util-linux 2.20.1
fsck.ext4:无效选项 -- h
Usage: fsck.ext4 [-panyrcdfvtDFV] [-b superblock] [-B blocksize]
                [-I inode_buffer_blocks] [-P process_inode_size]
                [-l|-L bad_blocks_file] [-C fd] [-j external_journal]
                [-E extended-options] device

Emergency help:
 -p                   Automatic repair (no questions)
 -n                   Make no changes to the filesystem
 -y                   Assume "yes" to all questions
 -c                   Check for bad blocks and add them to the badblock list
 -f                   Force checking even if filesystem is marked clean
 -v                   Be verbose
 -b superblock        Use alternative superblock
 -B blocksize         Force blocksize when looking for superblock
 -j external_journal  Set location of the external journal
 -l bad_blocks_file   Add to badblocks list
 -L bad_blocks_file   Set badblocks list
$ 
  • e2fsck命令:

fsck命令是一个总入口,它会根据具体分区的文件系统,调用具体对应的工具。例如ext2/3/4调用的是e2fsck工具。

$ ls -l /sbin/fsck*
-rwxr-xr-x 1 root root 30540  9月  3  2015 /sbin/fsck
-rwxr-xr-x 1 root root 13820  9月  3  2015 /sbin/fsck.cramfs
lrwxrwxrwx 1 root root     6  9月 10  2015 /sbin/fsck.ext2 -> e2fsck
lrwxrwxrwx 1 root root     6  9月 10  2015 /sbin/fsck.ext3 -> e2fsck
lrwxrwxrwx 1 root root     6  9月 10  2015 /sbin/fsck.ext4 -> e2fsck
lrwxrwxrwx 1 root root     6  9月 10  2015 /sbin/fsck.ext4dev -> e2fsck
-rwxr-xr-x 1 root root 54900  3月 18  2014 /sbin/fsck.fat
-rwxr-xr-x 1 root root 30292  9月  3  2015 /sbin/fsck.minix
lrwxrwxrwx 1 root root     8  5月  6  2015 /sbin/fsck.msdos -> fsck.fat
-rwxr-xr-x 1 root root   333  2月 17  2016 /sbin/fsck.nfs
lrwxrwxrwx 1 root root     8  5月  6  2015 /sbin/fsck.vfat -> fsck.fat

当你配置完fstab文件中pass选项以后,满心欢喜的执行fsck:

$ sudo fsck /dev/sdc1
fsck,来自 util-linux 2.20.1
e2fsck 1.42.9 (4-Feb-2014)
/dev/sdc1: clean, 14/6553600 files, 1452366/26214144 blocks

你会发现fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。

ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f选项调用fsck;

配置3.1:需要满足ext文件系统的check间隔时间,执行e2fsck才会启动真正的扫描和修复。

默认间隔为0,意味着就算执行e2fsck也不会真正的check。

$ sudo tune2fs -l /dev/sdc1
...
Last checked:             Tue Nov 12 15:35:53 2019
Check interval:           0 (<none>)
...

可以使用tune2fs -i命令来设置扫描间隔时间:

tune2fs -i 10 /dev/sdc1 10天后检查
tune2fs -i 1d /dev/sdc1 1天后检查
tune2fs -i 3w /dev/sdc1 3周后检查
tune2fs -i 6m /dev/sdc1 半年后检查
tune2fs -i 0 /dev/sdc1 禁用时间检查

配置3.2:或者满足mount次数达到限制,执行e2fsck才会启动真正的扫描和修复。

默认Maximum mount count-1,意味着就算执行e2fsck也不会真正的check。

$ sudo tune2fs -l /dev/sdc1
...
Mount count:              2
Maximum mount count:      -1
...

可以使用tune2fs -c命令来设置mount次数条件:

tune2fs -c 1 /dev/sdc1 设置每mount1次就进行一次check。
tune2fs -c -l /dev/sdc1 关闭强制检查挂载次数限制。

完整的文件系统检查和修复:

$ sudo fsck /dev/sdc1
fsck,来自 util-linux 2.20.1
e2fsck 1.42.9 (4-Feb-2014)
/dev/sdc1 has been mounted 2 times without being checked, 强制检查.
第一步: 检查inode,块,和大小
第二步: 检查目录结构
第3步: 检查目录连接性
Pass 4: Checking reference counts
第5步: 检查簇概要信息
/dev/sdc1: 14/6553600 files (0.0% non-contiguous), 1452366/26214144 blocks

2. Systemd 方式 (ubuntu 16.04 64bit)

systemd下面已经抛弃了mountall命令,它使用以下的local-fs.target关联的mount来加载分区,根据配置使用systemd-fsck-root.servicesystemd-fsck@.service来调用fsck。

 │ │ ├─local-fs.target
 │ │ │ ├─-.mount
 │ │ │ ├─home-root.mount
 │ │ │ ├─media-ram.mount
 │ │ │ ├─mnt-app.mount
 │ │ │ ├─systemd-fsck-root.service
 │ │ │ ├─systemd-remount-fs.service
 │ │ │ ├─tmp.mount
 │ │ │ ├─var-lib-machines.mount
 │ │ │ ├─var-volatile-lib.service
 │ │ │ └─var-volatile.mount

/lib/systemd/system/systemd-fsck-root.service:

[Unit]
Description=File System Check on Root Device
Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
Before=local-fs.target shutdown.target
ConditionPathIsReadWrite=!/

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck
TimeoutSec=0
~

/lib/systemd/system/systemd-fsck@.service:

[Unit]
Description=File System Check on %f
Documentation=man:systemd-fsck@.service(8)
DefaultDependencies=no
BindsTo=%i.device
After=%i.device systemd-fsck-root.service local-fs-pre.target
Before=shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck %f
TimeoutSec=0

2.1 普通分区的fsck

除了Root分区以外的普通分区使能fsck非常简单,直接使能fstab中的pass选项即可:

myc@myc-virtual-machine:~$ cat /etc/fstab 
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=bdc34999-c918-4a67-a92d-9bd7732e3820 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=f2fc9a8d-6ed3-4e59-8265-7aff14f95b98 none            swap    sw              0       0
UUID=1ec003be-8d57-414f-884e-5ebcfc2e5ac6 /home/myc/data  ext4    defaults        1        2
UUID=d9f51ab3-0053-4156-a175-e9732018ee16 /home/myc/vx    ext4    defaults        1        2 

最后的两个普通分区sdb1sdc1pass选项被配置成了2

重启系统在sudo journal -b的输出结果中查找fsck关键字,可以在系统启动日志中可以看到fsck的情况:

11月 14 18:05:11 myc-virtual-machine systemd-fsck[743]: /dev/sdb1: clean, 328353/2621440 files, 3552241/10485504 blocks
11月 14 18:05:11 myc-virtual-machine systemd-fsck[713]: /dev/sdc1: clean, 293466/6553600 files, 5998689/26214144 blocks

2.2 Root分区的fsck

  • 条件1:使能boot阶段的fsck

因为新版本的ubuntu默认是在initramfs阶段中进行Root分区的fsck,如果需要在磁盘文件系统的boot阶段进行fsck,首先需要打开使能配置:

# /lib/systemd/system/systemd-fsck-root.service
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=File System Check on Root Device
Documentation=man:systemd-fsck-root.service(8)
DefaultDependencies=no
Wants=systemd-fsckd.socket
Before=local-fs.target shutdown.target
After=systemd-fsckd.socket
ConditionPathIsReadWrite=!/
#ConditionPathExists=!/run/initramfs/fsck-root

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-fsck
TimeoutSec=0

注释掉ConditionPathExists=!/run/initramfs/fsck-root,这样才能使能。

  • 条件2:cmdline中的Root分区为ro
myc@myc-virtual-machine:~$ cat /proc/cmdline 
BOOT_IMAGE=/boot/vmlinuz-4.4.0-166-generic root=UUID=bdc34999-c918-4a67-a92d-9bd7732e3820 ro quiet splash

需要为ro,不能为rw

重启系统在sudo journal -b的输出结果中查找fsck关键字,可以在系统启动日志中可以看到fsck的情况:

11月 14 18:20:38 myc-virtual-machine systemd-fsck[404]: /dev/sda1: clean, 265631/1245184 files, 3177278/4980480 blocks

可以看到Root分区sda1也启动了fsck。

2.3 ext文件系统的限制

和上一章一样,调用fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。

ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f选项调用fsck;

条件1:需要满足ext文件系统的check间隔时间,执行e2fsck才会启动真正的扫描和修复。

默认间隔为0,意味着就算执行e2fsck也不会真正的check。

$ sudo tune2fs -l /dev/sdc1
...
Last checked:             Tue Nov 12 15:35:53 2019
Check interval:           0 (<none>)
...

可以使用tune2fs -i命令来设置扫描间隔时间:

tune2fs -i 10 /dev/sdc1 10天后检查
tune2fs -i 1d /dev/sdc1 1天后检查
tune2fs -i 3w /dev/sdc1 3周后检查
tune2fs -i 6m /dev/sdc1 半年后检查
tune2fs -i 0 /dev/sdc1 禁用时间检查

条件2:或者满足mount次数达到限制,执行e2fsck才会启动真正的扫描和修复。

默认Maximum mount count-1,意味着就算执行e2fsck也不会真正的check。

$ sudo tune2fs -l /dev/sdc1
...
Mount count:              2
Maximum mount count:      -1
...

可以使用tune2fs -c命令来设置mount次数条件:

tune2fs -c 1 /dev/sdc1 设置每mount1次就进行一次check。
tune2fs -c -l /dev/sdc1 关闭强制检查挂载次数限制。

重启系统在sudo journal -b的输出结果中查找fsck关键字,可以在系统启动日志中可以看到fsck完整扫描的情况:

11月 14 18:26:49 myc-virtual-machine systemd-fsck[715]: /dev/sdc1 has been mounted 6 times without being checked, 强制检查.

11月 14 18:26:52 myc-virtual-machine systemd-fsck[715]: /dev/sdc1: 293466/6553600 files (0.1% non-contiguous), 5998689/26214144 blocks

2.4 强制fsck完整扫描

可以在cmdline中添加fsck.mode=force选项使能所有的fsck操作进行强制完整扫描。

修改cmdline的方法:

1、首先在/etc/default/grub中的GRUB_CMDLINE_LINUX_DEFAULT后添加fsck.mode=force

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash fsck.mode=force"

2、然后使用update-grub命令更新配置;

重启系统在sudo journal -b的输出结果中查找fsck关键字,可以在系统启动日志中可以看到fsck完整扫描的情况:

11月 14 18:35:09 myc-virtual-machine systemd[1]: Starting File System Check on Root Device...
11月 14 18:35:10 myc-virtual-machine systemd-fsck[419]: /dev/sda1: 265631/1245184 files (0.2% non-contiguous), 3177338/4980480 blocks

11月 14 18:35:11 myc-virtual-machine systemd[1]: Starting File System Check on /dev/disk/by-uuid/d9f51ab3-0053-4156-a175-e9732018ee16...
11月 14 18:35:14 myc-virtual-machine systemd-fsck[786]: /dev/sdc1: 293466/6553600 files (0.1% non-contiguous), 5998689/26214144 blocks

11月 14 18:35:14 myc-virtual-machine systemd[1]: Started File System Check on /dev/disk/by-uuid/
11月 14 18:35:15 myc-virtual-machine systemd-fsck[785]: /dev/sdb1: 328353/2621440 files (0.1% non-contiguous), 3552241/10485504 blocks

2.5 fsck.repair

systemd-fsck 能够识别 下列cmdline:

fsck.mode=

检查模式。可设为 "auto", "force", "skip" 之一。 默认值 "auto" 表示 仅在文件系统检查工具认为确有必要的情况下, 才会实际执行真正的检查动作。"force" 表示无条件的执行检查动作。 "skip" 表示 无条件的跳过检查动作。

fsck.repair=

修复模式。可设为 "preen", "yes", "no" 之一。 默认值 "preen" 表示 自动修复文件系统检查过程中发现的可以安全修复的文件系统错误。 "yes" 表示对 fsck 询问的所有问题,一律回答"yes"。 "no" 表示对 fsck 询问的所有问题, 一律回答"no"。

3. Systemd 方式 (arm 32bit)

3.1 普通分区的fsck

除了Root分区以外的普通分区使能fsck非常简单,直接使能fstab中的pass选项即可:

# cat /etc/fstab 
# stock fstab - you probably want to override this with a machine specific one

/dev/root            /                    auto       defaults              1  1
proc                 /proc                proc       defaults              0  0
devpts               /dev/pts             devpts     mode=0620,gid=5       0  0
usbdevfs             /proc/bus/usb        usbdevfs   noauto                0  0
tmpfs                /run                 tmpfs      mode=0755,nodev,nosuid,strictatime 0  0
tmpfs                /var/volatile        tmpfs      defaults,size=50M     0  0
tmpfs                /media/ram           tmpfs      defaults,size=16M     0  0

/dev/mmcblk0p3       /mnt/app               ext4     rw,sync               0  2
/dev/mmcblk0p4       /home/root             ext4     rw,sync               0  2

最后的两个普通分区mmcblk0p3mmcblk0p4pass选项被配置成了2

重启系统在sudo journal -b的输出结果中查找Check关键字,可以在系统启动日志中可以看到fsck的情况:

Oct 03 21:06:15 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p3...                                              
Oct 03 21:06:15 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p4... 

3.2 Root分区的fsck

需要把cmdline中的Root分区设置为ro

# cat /proc/cmdline 
console=ttyO2,115200n8 root=PARTUUID=912ff182-02 ro rootfstype=ext4 rootwait

需要为ro,不能为rw

需要修改uboot代码:

include/configs/ti_armv7_common.h:

        "args_mmc=run finduuid;setenv bootargs console=${console} " \
                "${optargs} " \
                "root=PARTUUID=${uuid} ro " \
                "rootfstype=${mmcrootfstype}\0" \

重启系统在sudo journal -b的输出结果中查找Check关键字,可以在系统启动日志中可以看到fsck的情况:

Oct 03 21:06:12 am57xx-evm systemd[1]: Starting File System Check on Root Device...      

3.3 ext文件系统的限制

和上一章一样,调用fsck只是简单的打印出一些信息,并没有做完整的磁盘扫描。

ext2/3/4类型的文件系统在e2fsck被调用时,并不会执行完整的文件系统检查和修复。它需要满足以下任一条件才会启动:
1、文件系统被标记出错"dirty";
2、需要满足check间隔的时间 或者 mount的次数到达限制;
3、使用-f选项调用fsck;

3.4 强制fsck完整扫描

cmdline中添加fsck.mode=force选项使能所有的fsck操作进行强制完整扫描。

修改uboot代码:

include/configs/ti_armv7_common.h:

        "args_mmc=run finduuid;setenv bootargs console=${console} " \
                "${optargs} " \
                "root=PARTUUID=${uuid} ro " \
                "rootfstype=${mmcrootfstype} fsck.mode=force\0" \

查看cmdline:


重启系统在sudo journal -b的输出结果中查找Check关键字,可以在系统启动日志中可以看到fsck的情况:

Oct 03 21:06:12 am57xx-evm systemd[1]: Starting File System Check on Root Device...  
Oct 03 21:06:14 am57xx-evm systemd-fsck[118]: rootfs: 62308/205504 files (0.1% non-contiguous), 573431/821248 blocks

Oct 03 21:06:17 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p3...                                                              
Oct 03 21:06:17 am57xx-evm systemd[1]: Starting File System Check on /dev/mmcblk0p4...       
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:23 天前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐