认识 Linux 文件系统

文件系统特性

例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。 文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data block 区块中。 另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。

每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:

  • superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;

  • inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block号码;

  • block:实际记录文件的内容,若文件太大时,会占用多个 block 。

inode/block 数据存取示意图

某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为 2, 7, 13, 15 这四个 block 号码

这种数据存取的方法我们称为索引式文件系统(indexed allocation)

FAT文件系统数据存取示意图

文件的数据依序写入1->7->4->15号这四个 block 号码中, 但这个文件系统没
有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个block 在何处。 如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!

Linux 的 EXT2 文件系统(inode)

Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统。

ext2文件系统示意图

  • 文件系统最前面有一个开机扇区(boot sector),这个开机扇区可以安装开机管理程序

每一个区块群组(block group)的六个主要内容:

  • data block (数据区块)

    data block 是用来放置文件内容数据地方。

    Block 大小1KB 2KB 4KB
    最大单一文件限制 16GB 256GB 2TB
    最大文件系统总容量 2TB 8TB 16TB

    Ext2 文件系统的 block 基本限制如下:

    • 原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
    • 每个 block 内最多只能够放置一个文件的数据;
    • 承上,如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
    • 承上,若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)。
  • inode table (inode 表格)

    inode 是记录文件的属性以及该文件实际数据是放置在哪几个 block。

    • 该文件的存取模式(read/write/excute);

    • 该文件的拥有者与群组(owner/group);

    • 该文件的容量;

    • 该文件创建或状态改变的时间(ctime);

    • 最近一次的读取时间(atime);

    • 最近修改的时间(mtime);

    • 定义文件特性的旗标(flag),如 SetUID…;

    • 该文件真正内容的指向 (pointer);

      其他特点:

    • 每个 inode 大小均固定为 128 Bytes (新的 ext4 与 xfs 可设置到 256 Bytes);

    • 每个文件都仅会占用一个 inode 而已;

    • 承上,因此文件系统能够创建的文件数量与 inode 的数量有关;

    • 系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容。

      inode 结构示意图

      上图最左边为 inode 本身 (128 Bytes),里面有 12 个直接指向 block 号码的对照,这 12 笔记录就能够直接取得 block 号码啦! 至于所谓的间接就是再拿一个 block 来当作记录 block 号码的记录区,如果文件太大时, 就会使用间接的 block 来记录号码。

  • Superblock (超级区块)

    Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个filesystem 了

    记录的信息主要有:

    • block 与 inode 的总量;

    • 未使用与已使用的 inode / block 数量;

    • block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128Bytes 或 256Bytes);

    • filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;

    • 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。

      此外,每个 block group 都可能含有 superblock。
      一般除第一个block group会有superblock,后续如果有的话,就是给第一个 block group 内 superblock 的备份,以后可以做恢复使用。

  • Filesystem Description(文件系统描述说明)

    这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段(superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间。

  • block bitmap (区块对照表)

    记录的是使用与未使用的 block 号码

  • inode bitmap (inode 对照表)

    记录使用与未使用的 inode 号码

  • dumpe2fs: 查询 Ext 家族 superblock 信息的指令

1
2
3
4
[root@study ~]$ dumpe2fs [-bh] 设备文件名
选项与参数:
-b :列出保留为坏轨的部分(一般用不到吧!?)
-h :仅列出 superblock 的数据,不会列出其他的区段内容!

与目录树的关系

目录

当我们在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码;而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据。也就是说目录所占用的 block 内容在记录如下的信息:

记载于目录所属的 block 内的文件名与 inode 号码对应示意图

文件

当我们在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小的 block 数量给该文件。例如:假设我的一个 block 为 4 KBytes ,而我要创建一个 100 KBytes 的文件,那么 linux 将分配一个 inode 与 25 个 block 来储存该文件! 但同时请注意,由于 inode 仅有 12 个直接指向,因此还要多一个 block 来作为区块号码的记录喔!

目录树读取

1
2
3
4
[root@study ~]$ ll -di / /etc /etc/passwd
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
33595521 drwxr-xr-x. 131 root root 8192 Jun 17 00:20 /etc
36628004 -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd

该文件的读取流程为:

  1. / 的 inode: 通过挂载点的信息找到 inode 号码为 128 的根目录 inode,且 inode 规范的权限让我们可以读取该 block 的内容(有 r 与 x) ;
  2. / 的 block: 经过上个步骤取得 block 的号码,并找到该内容有 etc/ 目录的 inode 号码(33595521);
  3. etc/ 的 inode: 读取 33595521 号 inode 得知 dmtsai 具有 r 与 x 的权限,因此可以读取etc/ 的 block 内容;
  4. etc/ 的 block: 经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 (36628004);
  5. passwd 的 inode: 读取 36628004 号 inode 得知 dmtsai 具有 r 的权限,因此可以读取 passwd 的 block 内容;
  6. passwd 的 block: 最后将该 block 内容的数据读出来。
  7. filesystem 大小与磁盘读取性能:如果文件写入的 block 真的分的很散, 此时就会有所谓的文件数据离散的问题发生了。(文件太大)

EXT2/EXT3/EXT4 文件的存取与日志式文件系统的功能

新增一个文件,此时文件系统的行为是:

  1. 先确定使用者对于欲新增文件的目录是否具有 w 与 x 的权限,若有的话才能新增;
  2. 根据 inode bitmap 找到没有使用的 inode 号码,并将新文件的权限/属性写入;
  3. 根据 block bitmap 找到没有使用中的 block 号码,并将实际的数据写入 block 中,且更新 inode 的 block 指向数据;
  4. 将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap,并更新superblock 的内容。

inode table 与 data block 称为数据存放区域。
superblock、block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据),因为 superblock, inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响到这三个部分的数据,所以被称为中介数据。

数据的不一致 (Inconsistent) 状态

意外导致文件数据的不完整。

日志式文件系统 (Journaling filesystem)

  1. 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
  2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
  3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。

Linux 文件系统的运行

  • 系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写;
  • 承上,因此 Linux 的实体内存最后都会被用光!这是正常的情况!可加速系统性能;
  • 你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;
  • 若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
  • 但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。

挂载点的意义 (mount point)

每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。 将文件系统与目录树结合的动作我们称为“挂载”。

其他 Linux 支持的文件系统与 VFS

  • 传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;
  • 日志式文件系统: ext3 / ext4 / ReiserFS / Windows’ NTFS / IBM’s JFS / SGI’s XFS / ZFS
  • 网络文件系统: NFS / SMBFS

Linux VFS (Virtual Filesystem Switch)

整个 Linux 的系统都是通过一个名为 Virtual Filesystem Switch 的核
心功能去读取 filesystem 的。

VFS 文件系统的示意图

XFS 文件系统简介

CentOS 7 开始,默认的文件系统已经由原本的 EXT4 变成了 XFS 文件系统

为什么要从EXT4 -> XFS?

  • EXT 家族当前较伤脑筋的地方:支持度最广,但格式化超慢!

查看XFS xfs_info

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@study ~]$ xfs_info 挂载点 | 设备文件名
范例一:找出系统 /boot 这个挂载点下面的文件系统的 superblock 纪录
[root@study ~]$ df -T /boot
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/vda2 xfs 1038336 133704 904632 13% /boot
# 没错!可以看得出来是 xfs 文件系统的!来观察一下内容吧!
[root@study ~]$ xfs_info /dev/vda2
1 meta-data=/dev/vda2 isize=256 agcount=4, agsize=65536 blks
2 = sectsz=512 attr=2, projid32bit=1
3 = crc=0 finobt=0
4 data = bsize=4096 blocks=262144, imaxpct=25
5 = sunit=0 swidth=0 blks
6 naming =version 2 bsize=4096 ascii-ci=0 ftype=0
7 log =internal bsize=4096 blocks=2560, version=2
8 = sectsz=512 sunit=0 blks, lazy-count=1
9 realtime =none extsz=4096 blocks=0, rtextents=0

上面的输出讯息可以这样解释:

  • 第 1 行里面的 isize 指的是 inode 的容量,每个有 256Bytes 这么大。至于 agcount 则是前面谈到的储存区群组 (allocation group) 的个数,共有 4 个, agsize 则是指每个储存区群组具有 65536 个 block 。配合第 4 行的 block 设置为 4K,因此整个文件系统的容量应该就是 4655364K 这么大!
  • 第 2 行里面 sectsz 指的是逻辑扇区 (sector) 的容量设置为 512Bytes 这么大的意思。
  • 第 4 行里面的 bsize 指的是 block 的容量,每个 block 为 4K 的意思,共有 262144 个 block 在这个文件系统内。
  • 第 5 行里面的 sunit 与 swidth 与磁盘阵列的 stripe 相关性较高。
  • 第 7 行里面的 internal 指的是这个登录区的位置在文件系统内,而不是外部设备的意思。且占用了 4K * 2560 个 block,总共约 10M 的容量。
  • 第 9 行里面的 realtime 区域,里面的 extent 容量为 4K。不过目前没有使用。

文件系统的简单操作

磁盘与目录的容量

  • df:列出文件系统的整体磁盘使用量;
  • du:评估文件系统的磁盘使用量(常用在推估目录所占容量)

df

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@study ~]$ df [-ahikHTm] [目录或文件名]
选项与参数:
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k :以 KBytes 的容量显示各文件系统;
-m :以 MBytes 的容量显示各文件系统;
-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H :以 M=1000K 取代 M=1024K 的进位方式;
-T :连同该 partition 的 filesystem 名称 (例如 xfs) 也列出;
-i :不用磁盘容量,而以 inode 的数量来显示
范例一:将系统内所有的 filesystem 列出来!
[root@study ~]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/centos-root 10475520 3409408 7066112 33% /
devtmpfs 627700 0 627700 0% /dev
tmpfs 637568 80 637488 1% /dev/shm
tmpfs 637568 24684 612884 4% /run
tmpfs 637568 0 637568 0% /sys/fs/cgroup
/dev/mapper/centos-home 5232640 67720 5164920 2% /home
/dev/vda2 1038336 133704 904632 13% /boot
# 在 Linux 下面如果 df 没有加任何选项,那么默认会将系统内所有的
# (不含特殊内存内的文件系统与 swap) 都以 1 KBytes 的容量来列出来!
# 至于那个 /dev/shm 是与内存有关的挂载,先不要理他!
  • Filesystem:代表该文件系统是在哪个 partition ,所以列出设备名称;
  • 1k-blocks:说明下面的数字单位是 1KB 呦!可利用 -h 或 -m 来改变容量;
  • Used:顾名思义,就是使用掉的磁盘空间啦!
  • Available:也就是剩下的磁盘空间大小;
  • Use%:就是磁盘的使用率啦!如果使用率高达 90% 以上时, 最好需要注意一下了,免得容量不足造成系统问题喔!(例如最容易被灌爆的 /var/spool/mail 这个放置邮件的磁盘)
  • Mounted on:就是磁盘挂载的目录所在啦!(挂载点啦!)

du

1
2
3
4
5
6
7
8
[root@study ~]$ du [-ahskm] 文件或目录名称
选项与参数:
-a :列出所有的文件与目录容量,因为默认仅统计目录下面的文件量而已。
-h :以人们较易读的容量格式 (G/M) 显示;
-s :列出总量而已,而不列出每个各别的目录占用容量;
-S :不包括子目录下的总计,与 -s 有点差别。
-k :以 KBytes 列出容量显示;
-m :以 MBytes 列出容量显示;

与 df 不一样的是,du 这个指令其实会直接到文件系统内去搜寻所有的文件数据

实体链接与符号链接: ln

  • 每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;
  • 想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。
1
2
3
4
5
6
[root@study ~]$ ll -i /etc/crontab
34474855 -rw-r--r--. 1 root root 451 Jun 10 2014 /etc/crontab
[root@study ~]$ ln /etc/crontab . <==创建实体链接的指令
[root@study ~]$ ll -i /etc/crontab crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab

“链接” 从 1 变成 2 ,这个字段的意义为:“有多少个文件名链接到这个 inode 号码”的意思。

实体链接的文件读
取示意图

hard link 的制作中,其实还是可能会改变系统的 block 的,那就是当你新增这笔数据却刚好将目录的 block 填满时,就可能会新加一个 block 来记录文件名关连性,而导致磁盘空间的变化!不过,一般 hard link 所用掉的关连数据量很小,所以通常不会改变 inode 与磁盘空间的大小喔!

一般来说,使用 hard link 设置链接文件时,磁盘的空间与 inode 的数目都不会改变! 由图中可以知道, hard link 只是在某个目录下的 block 多写入一个关连数据而已,既不会增加 inode 也不会耗用 block 数量哩!

hard link 是有限制的:

  • 不能跨 Filesystem;
  • 不能 link 目录。

Symbolic link 可就好理解多了,基本上, Symbolic link 就是在创建一个
独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的文件名!由于只是利用文件来做为指向的动作, 所以,当来源文件被删除之后,symbolic link 的文件会“开不了”, 会一直说“无法打开某文件!”。实际上就是找不到原始“文件名”而已啦!

1
2
3
4
5
6
[root@localhost ~]$ ll /etc/crontab ./crontab.*
-rw-r--r--. 1 root root 451 Sep 24 10:09 ./crontab.cp
-rw-r--r--. 1 root root 451 Jun 10 2014 ./crontab.cpp
-rw-r--r--. 2 root root 451 Jun 10 2014 ./crontab.hard
lrwxrwxrwx. 1 root root 12 Sep 24 10:08 ./crontab.soft -> /etc/crontab
-rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab

符号链接的文件读
取示意图

这里还是得特别留意,这个 Symbolic Link 与 Windows 的捷径可以给他划上等号,由Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉 inode 与 block 喔!

1
2
3
4
[root@study ~]$ ln [-sf] 来源文件 目标文件
选项与参数:
-s :如果不加任何参数就进行链接,那就是hard link,至于 -s 就是symbolic link
-f :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建!

磁盘的分区、格式化、检验与挂载

  1. 对磁盘进行分区,以创建可用的 partition ;
  2. 对该 partition 进行格式化 (format),以创建系统可用的 filesystem;
  3. 若想要仔细一点,则可对刚刚创建好的 filesystem 进行检验;
  4. 在 Linux 系统上,需要创建挂载点 (亦即是目录),并将他挂载上来;

观察磁盘分区状态

lsblk 列出系统上的所有磁盘列表

lsblk 可以看成“ list block device ”的缩写,就是列出所有储存设备的意思!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@study ~]$ lsblk [-dfimpt] [device]
选项与参数:
-d :仅列出磁盘本身,并不会列出该磁盘的分区数据
-f :同时列出该磁盘内的文件系统名称
-i :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用)
-m :同时输出该设备在 /dev 下面的权限数据 (rwx 的数据)
-p :列出该设备的完整文件名!而不是仅列出最后的名字而已。
-t :列出该磁盘设备的详细数据,包括磁盘伫列机制、预读写的数据量大小等

范例一:列出本系统下的所有磁盘与磁盘内的分区信息
[root@localhost ~]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 127G 0 disk
├─sda1 8:1 0 2M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 35G 0 part
├─centos-root 253:0 0 30G 0 lvm /
├─centos-swap 253:1 0 4M 0 lvm [SWAP]
└─centos-home 253:2 0 5G 0 lvm /home
sr0 11:0 1 1024M 0 rom
  • NAME:就是设备的文件名啰!会省略 /dev 等前导目录
  • MAJ:MIN:其实核心认识的设备都是通过这两个代码来熟悉的!分别是主要:次要设备代码
  • RM:是否为可卸载设备 (removable device),如光盘、USB 磁盘等等
  • SIZE:容量
  • RO:是否为只读设备的意思
  • TYPE:是磁盘 (disk)、分区 (partition) 还是只读存储器 (rom)等输出
  • MOUTPOINT:挂载点

blkid 列出设备的 UUID 等参数

什么是 UUID 呢?UUID 是全域单一识别码(universally unique identifier),Linux 会将系统内所有的设备都给予一个独一无二的识别码, 这个识别码就可以拿来作为挂载或者是使用这个设备/文件系统之用了。

1
2
3
4
5
6
[root@localhost ~]$ blkid
/dev/sda2: UUID="243cc327-5655-4a87-8178-3f59be083031" TYPE="xfs" PARTUUID="30d4a8e1-88b3-43de-8b76-40aef253a15b"
/dev/sda3: UUID="v7xjPn-WCbG-Wuvw-oXr3-Ju9N-yBEk-fJf1Am" TYPE="LVM2_member" PARTUUID="cdfb7a99-8532-48d9-8e2e-662af2e5ce69"
/dev/mapper/centos-root: UUID="c2ada878-3d9f-4dff-a68f-fa237ab94968" TYPE="xfs"
/dev/mapper/centos-swap: UUID="f4fccc29-4a38-4ca1-8f8f-99b99fa4fde1" TYPE="swap"
/dev/mapper/centos-home: UUID="ae0ce3d3-db6e-4989-b8ff-7b88fd1e88b6" TYPE="xfs"

parted 列出磁盘的分区表类型与分区信息

1
2
3
4
5
6
7
8
9
10
11
12
[root@study ~]$ parted device_name print
范例一:列出 /dev/vda 磁盘的相关数据
[root@study ~]$ parted /dev/vda print
Model: Virtio Block Device (virtblk) # 磁盘的模块名称(厂商)
Disk /dev/vda: 42.9GB # 磁盘的总容量
Sector size (logical/physical): 512B/512B # 磁盘的每个逻辑/物理扇区容量
Partition Table: gpt # 分区表的格式 (MBR/GPT)
Disk Flags: pmbr_boot
Number Start End Size File system Name Flags # 下面才是分区数据
1 1049kB 3146kB 2097kB bios_grub
2 3146kB 1077MB 1074MB xfs
3 1077MB 33.3GB 32.2GB lvm

磁盘分区: gdisk/fdisk

MBR 分区表请使用 fdisk 分区, GPT 分区表请使用 gdisk 分区

gdisk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@study ~]$ gdisk 设备名称
范例:由前一小节的 lsblk 输出,我们知道系统有个 /dev/vda,请观察该磁盘的分区与相关数据
[root@study ~]$ gdisk /dev/vda <==仔细看,不要加上数字喔!
GPT fdisk (gdisk) version 0.8.6
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT. <==找到了 GPT 的分区表!
Command (? for help): &lt;==这里可以让你输入指令动作,可以按问号 (?) 来查看可用指令
Command (? for help): ?
b back up GPT data to a file
c change a partition's name
d delete a partition # 删除一个分区
i show detailed information on a partition
l list known partition types
n add a new partition # 增加一个分区
o create a new empty GUID partition table (GPT)
p print the partition table # 印出分区表 (常用)
q quit without saving changes # 不储存分区就直接离开 gdisk
r recovery and transformation options (experts only)
s sort partitions
t change a partition's type code
v verify disk
w write table to disk and exit # 储存分区操作后离开 gdisk
x extra functionality (experts only)
? print this menu
Command (? for help):

你应该要通过 lsblkblkid 先找到磁盘,再用 parted /dev/xxx print 来找出内部的分区表类型,之后才用 gdiskfdisk 来操作系统。

partprobe 更新 Linux 核心的分区表信息

1
2
[root@study ~]$ partprobe [-s] # 你可以不要加 -s !那么屏幕不会出现讯息!
[root@study ~]$ partprobe -s # 不过还是建议加上 -s 比较清晰!

磁盘格式化(创建文件系统)

XFS 文件系统 mkfs.xfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@study ~]$ mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-L label] [-f] \
[-r parms] 设备名称
选项与参数:
关於单位:下面只要谈到“数值”时,没有加单位则为 Bytes 值,可以用 k,m,g,t,p (小写)等来解释
比较特殊的是 s 这个单位,它指的是 sector 的“个数”喔!
-b :后面接的是 block 容量,可由 512 到 64k,不过最大容量限制为 Linux 的 4k 喔!
-d :后面接的是重要的 data section 的相关参数值,主要的值有:
agcount=数值 :设置需要几个储存群组的意思(AG),通常与 CPU 有关
agsize=数值 :每个 AG 设置为多少容量的意思,通常 agcount/agsize 只选一个设置即可
file :指的是“格式化的设备是个文件而不是个设备”的意思!(例如虚拟磁盘)
size=数值 :data section 的容量,亦即你可以不将全部的设备容量用完的意思
su=数值 :当有 RAID 时,那个 stripe 数值的意思,与下面的 sw 搭配使用
sw=数值 :当有 RAID 时,用于储存数据的磁盘数量(须扣除备份碟与备用碟)
sunit=数值 :与 su 相当,不过单位使用的是“几个 sector(512Bytes大小)”的意思
swidth=数值 :就是 su*sw 的数值,但是以“几个 sector(512Bytes大小)”来设置
-f :如果设备内已经有文件系统,则需要使用这个 -f 来强制格式化才行!
-i :与 inode 有较相关的设置,主要的设置值有:
size=数值 :最小是 256Bytes 最大是 2k,一般保留 256 就足够使用了!
internal=[0&#124;1]:log 设备是否为内置?默认为 1 内置,如果要用外部设备,使用下面设置
logdev=device :log 设备为后面接的那个设备上头的意思,需设置 internal=0 才可!
size=数值 :指定这块登录区的容量,通常最小得要有 512 个 block,大约 2M 以上才行!
-L :后面接这个文件系统的标头名称 Label name 的意思!
-r :指定 realtime section 的相关设置值,常见的有:
extsize=数值 :就是那个重要的 extent 数值,一般不须设置,但有 RAID 时,
最好设置与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。

EXT4 文件系统 mkfs.ext4

1
2
3
4
[root@study ~]$ mkfs.ext4 [-b size] [-L label] 设备名称
选项与参数:
-b :设置 block 的大小,有 1K, 2K, 4K 的容量,
-L :后面接这个设备的标头名称。

文件系统检验

xfs_repair 处理 XFS 文件系统

1
2
3
4
5
[root@study ~]$ xfs_repair [-fnd] 设备名称
选项与参数:
-f :后面的设备其实是个文件而不是实体设备
-n :单纯检查并不修改文件系统的任何数据 (检查而已)
-d :通常用在单人维护模式下面,针对根目录 (/) 进行检查与修复的动作!很危险!不要随便使用

fsck.ext4 处理 EXT4 文件系统

1
2
3
4
5
6
7
8
9
[root@study ~]$ fsck.ext4 [-pf] [-b superblock] 设备名称
选项与参数:
-p :当文件系统在修复时,若有需要回复 y 的动作时,自动回复 y 来继续进行修复动作。
-f :强制检查!一般来说,如果 fsck 没有发现任何 unclean 的旗标,不会主动进入
细部检查的,如果您想要强制 fsck 进入细部检查,就得加上 -f 旗标啰!
-D :针对文件系统下的目录进行最优化配置。
-b :后面接 superblock 的位置!一般来说这个选项用不到。但是如果你的 superblock 因故损毁时,
通过这个参数即可利用文件系统内备份的 superblock 来尝试救援。一般来说,superblock 备份在:
1K block 放在 8193, 2K block 放在 16384, 4K block 放在 32768

文件系统挂载与卸载

  • 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
  • 单一目录不应该重复挂载多个文件系统;
  • 要作为挂载点的目录,理论上应该都是空目录才是。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@study ~]$ mount -a
[root@study ~]$ mount [-l]
[root@study ~]$ mount [-t 文件系统] LABEL='' 挂载点
[root@study ~]$ mount [-t 文件系统] UUID='' 挂载点 # 建议用这种方式
[root@study ~]$ mount [-t 文件系统] 设备文件名 挂载点
选项与参数:
-a :依照配置文件 [/etc/fstab](../Text/index.html#fstab) 的数据将所有未挂载的磁盘都挂载上来
-l :单纯的输入 mount 会显示目前挂载的信息。加上 -l 可增列 Label 名称!
-t :可以加上文件系统种类来指定欲挂载的类型。常见的 Linux 支持类型有:xfs, ext3, ext4,
reiserfs, vfat, iso9660(光盘格式), nfs, cifs, smbfs (后三种为网络文件系统类型)
-n :在默认的情况下,系统会将实际挂载的情况实时写入 /etc/mtab 中,以利其他程序的运行。
但在某些情况下(例如单人维护模式)为了避免问题会刻意不写入。此时就得要使用 -n 选项。
-o :后面可以接一些挂载时额外加上的参数!比方说帐号、密码、读写权限等:
async, sync: 此文件系统是否使用同步写入 (sync) 或非同步 (async) 的
内存机制,请参考[文件系统运行方式](../Text/index.html#harddisk-filerun)。默认为 async。
atime,noatime: 是否修订文件的读取时间(atime)。为了性能,某些时刻可使用 noatime
ro, rw: 挂载文件系统成为只读(ro) 或可读写(rw)
auto, noauto: 允许此 filesystem 被以 mount -a 自动挂载(auto)
dev, nodev: 是否允许此 filesystem 上,可创建设备文件? dev 为可允许
suid, nosuid: 是否允许此 filesystem 含有 suid/sgid 的文件格式?
exec, noexec: 是否允许此 filesystem 上拥有可执行 binary 文件?
user, nouser: 是否允许此 filesystem 让任何使用者执行 mount ?一般来说,
mount 仅有 root 可以进行,但下达 user 参数,则可让
一般 user 也能够对此 partition 进行 mount 。
defaults: 默认值为:rw, suid, dev, exec, auto, nouser, and async
remount: 重新挂载,这在系统出错,或重新更新参数时,很有用!

重新挂载根目录与挂载不特定目录

1
2
范例:将 / 重新挂载,并加入参数为 rw 与 auto
[root@study ~]$ mount -o remount,rw,auto /

重点是那个“ -o remount,xx ”的选项与参数!请注意,要重新挂载 (remount) 时, 这是个非常重要的机制!尤其是当你进入单人维护模式时,你的根目录常会被系统挂载为只读,这个时候这个指令就太重要了!

1
2
3
4
5
6
7
8
9
范例:将 /var 这个目录暂时挂载到 /data/var 下面:
[root@study ~]$ mkdir /data/var
[root@study ~]$ mount --bind /var /data/var
[root@study ~]$ ls -lid /var /data/var
16777346 drwxr-xr-x. 22 root root 4096 Jun 15 23:43 /data/var
16777346 drwxr-xr-x. 22 root root 4096 Jun 15 23:43 /var
# 内容完全一模一样啊!因为挂载目录的缘故!
[root@study ~]$ mount &#124; grep var
/dev/mapper/centos-root on /data/var type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

看起来,其实两者链接到同一个 inode 嘛! ^_^ 没错啦!通过这个 mount –bind 的功能, 您
可以将某个目录挂载到其他目录去喔!而并不是整块 filesystem 的啦!所以从此进入
/data/var 就是进入 /var 的意思喔!

umount (将设备文件卸载)

1
2
3
4
5
[root@study ~]$ umount [-fn] 设备文件名或挂载点
选项与参数:
-f :强制卸载!可用在类似网络文件系统 (NFS) 无法读取到的情况下;
-l :立刻卸载文件系统,比 -f 还强!
-n :不更新 /etc/mtab 情况下卸载。

磁盘/文件系统参数修订

mknod

1
2
3
4
5
[root@localhost ~]$ ll /dev/sda*
brw-rw----. 1 root disk 8, 0 Sep 24 16:36 /dev/sda
brw-rw----. 1 root disk 8, 1 Sep 17 14:33 /dev/sda1
brw-rw----. 1 root disk 8, 2 Sep 17 14:33 /dev/sda2
brw-rw----. 1 root disk 8, 3 Sep 17 14:33 /dev/sda3

上表当中 252 为主要设备代码 (Major) 而 0~5 则为次要设备代码 (Minor)。 我们的Linux 核心认识的设备数据就是通过这两个数值来决定的!举例来说,常见的磁盘文件名/dev/sda/dev/loop0 设备代码如下所示:

磁盘文件名 Major Minor
/dev/sda 8 0-15
/dev/sdb 8 16-31
/dev/loop0 7 0
/dev/loop1 7 1
1
2
3
4
5
6
7
8
[root@study ~]$ mknod 设备文件名 [bcp] [Major] [Minor]
选项与参数:
设备种类:
b :设置设备名称成为一个周边储存设备文件,例如磁盘等;
c :设置设备名称成为一个周边输入设备文件,例如鼠标/键盘等;
p :设置设备名称成为一个 FIFO 文件;
Major :主要设备代码;
Minor :次要设备代码;

xfs_admin 修改 XFS 文件系统的 UUID 与 Label name

如果你当初格式化的时候忘记加上标头名称,后来想要再次加入时,不需要重复格式化!直接使用这个 xfs_admin 即可。 这个指令直接拿来处理 LABEL name 以及 UUID 即可啰!

1
2
3
4
5
6
[root@study ~]$ xfs_admin [-lu] [-L label] [-U uuid] 设备文件名
选项与参数:
-l :列出这个设备的 label name
-u :列出这个设备的 UUID
-L :设置这个设备的 Label name
-U :设置这个设备的 UUID

tune2fs 修改 ext4 的 label name 与 UUID

1
2
3
4
5
[root@study ~]$ tune2fs [-l] [-L Label] [-U uuid] 设备文件名
选项与参数:
-l :类似 dumpe2fs -h 的功能~将 superblock 内的数据读出来~
-L :修改 LABEL name
-U :修改 UUID

设置开机挂载

开机挂载 /etc/fstab 及 /etc/mtab

系统挂载的一些限制:

  • 根目录 / 是必须挂载的﹐而且一定要先于其它 mount point 被挂载进来。
  • 其它 mount point 必须为已创建的目录﹐可任意指定﹐但一定要遵守必须的系统目录架构原则 (FHS)
  • 所有 mount point 在同一时间之内﹐只能挂载一次。
  • 所有 partition 在同一时间之内﹐只能挂载一次。
  • 如若进行卸载﹐您必须先将工作目录移到 mount point(及其子目录) 之外。
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]$ cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Wed Sep 9 06:03:58 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=243cc327-5655-4a87-8178-3f59be083031 /boot xfs defaults 0 0
/dev/mapper/centos-home /home xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0

[设备/UUID等] [挂载点] [文件系统] [文件系统参数] [dump] [fsck]

文件系统参数 内容意义
async/sync
非同步/同步
设置磁盘是否以非同步方式运行!默认为 async(性能较佳)
auto/noauto
自动/非自动
当下达 mount -a 时,此文件系统是否会被主动测试挂载。默认为 auto。
rw/ro 可读
写/只读
让该分区以可读写或者是只读的型态挂载上来,如果你想要分享的数据是不给使用者随意变更的, 这里也能够设置为只读。则不论在此文件系统的文件是否设置 w 权限,都无法写入喔!
exec/noexec
可执行/不可执行
限制在此文件系统内是否可以进行“执行”的工作?如果是纯粹用来储存数据的目录, 那么可以设置为 noexec 会比较安全。不过,这个参数也不能随便使用,因为你不知道该目录下是否默认会有可执行文件。举例来说,如果你将 noexec 设置在 /var ,当某些软件将一些可执行文件放置于 /var 下时,那就会产生很大的问题喔! 因此,建议这个 noexec 最多仅设置于你自订或分享的一般数据目录。
user/nouser
允许/不允许使用者挂载
是否允许使用者使用 mount指令来挂载呢?一般而言,我们当然不希望一般身份的 user 能使用 mount 啰,因为太不安全了,因此这里应该要设置为 nouser 啰!
suid/nosuid
具有/不具有suid 权限
该文件系统是否允许 SUID 的存在?如果不是可执行文件放置目录,也可以设置为 nosuid 来取消这个功能!
defaults 同时具有 rw, suid, dev, exec, auto, nouser, async 等参数。 基本上,默认情况使用 defaults 设置即可!

特殊设备 loop 挂载 (镜像文件不烧录就挂载使用)

挂载光盘/DVD镜像文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@study ~]$ ll -h /tmp/CentOS-7.0-1406-x86_64-DVD.iso
-rw-r--r--. 1 root root 3.9G Jul 7 2014 /tmp/CentOS-7.0-1406-x86_64-DVD.iso
# 看到上面的结果吧!这个文件就是镜像文件,文件非常的大吧!
[root@study ~]$ mkdir /data/centos_dvd
[root@study ~]$ mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /data/centos_dvd
[root@study ~]$ df /data/centos_dvd
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 4050860 4050860 0 100% /data/centos_dvd
# 就是这个项目! .iso 镜像文件内的所有数据可以在 /data/centos_dvd 看到!
[root@study ~]$ ll /data/centos_dvd
total 607
-rw-r--r--. 1 500 502 14 Jul 5 2014 CentOS_BuildTag <==瞧!就是DVD的内容啊!
drwxr-xr-x. 3 500 502 2048 Jul 4 2014 EFI
-rw-r--r--. 1 500 502 611 Jul 5 2014 EULA
-rw-r--r--. 1 500 502 18009 Jul 5 2014 GPL
drwxr-xr-x. 3 500 502 2048 Jul 4 2014 images
.....(下面省略).....
[root@study ~]$ umount /data/centos_dvd/
# 测试完成!记得将数据给他卸载!同时这个镜像文件也被鸟哥删除了...测试机容量不够大!

创建大文件以制作 loop 设备文件!

如果当初在分区时, 你只有分区出一个根目录,假设你已经没有多余的容量可以进行额外的分区的!偏偏根目录的容量还很大! 此时你就能够制作出一个大文件,然后将这个文件挂载!如此一来感觉上你就多了一个分区啰!用途非常的广泛啦!

创建大型文件

1
2
3
4
5
6
7
8
9
10
11
[root@study ~]$ dd if=/dev/zero of=/srv/loopdev bs=1M count=512
512+0 records in &lt;==读入 512 笔数据
512+0 records out &lt;==输出 512 笔数据
536870912 Bytes (537 MB) copied, 12.3484 seconds, 43.5 MB/s
# 这个指令的简单意义如下:
# if 是 input file ,输入文件。那个 /dev/zero 是会一直输出 0 的设备!
# of 是 output file ,将一堆零写入到后面接的文件中。
# bs 是每个 block 大小,就像文件系统那样的 block 意义;
# count 则是总共几个 bs 的意思。所以 bs*count 就是这个文件的容量了!
[root@study ~]$ ll -h /srv/loopdev
-rw-r--r--. 1 root root 512M Jun 25 19:46 /srv/loopdev

大型文件的格式化

1
2
3
[root@study ~]$ mkfs.xfs -f /srv/loopdev
[root@study ~]$ blkid /srv/loopdev
/srv/loopdev: UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" TYPE="xfs"

挂载

利用 mount 的特殊参数,那个 -o loop 的参数来处理!

1
2
3
4
[root@study ~]$ mount -o loop UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" /mnt
[root@study ~]$ df /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 520876 26372 494504 6% /mnt

CentOS 7.x 越来越聪明了,现在你不需要下达 -o loop 这个选项与参数,它同样可以被系统挂上来! 连直接输入 blkid 都会列出这个文件内部的文件系统耶!相当有趣!不过,为了考虑向下兼容性,鸟哥还是建议你加上 loop 比较妥当喔! 现在,请将这个文件系统永远的自动挂载起来吧!

内存交换空间(swap)之创建

使用实体分区创建swap

创建 swap 分区的步骤:

  1. 分区:先使用 gdisk 在你的磁盘中分区出一个分区给系统作为 swap 。由于 Linux 的
    gdisk 默认会将分区的 ID 设置为 Linux 的文件系统,所以你可能还得要设置一下 system ID 就是了。
  2. 格式化:利用创建 swap 格式的“mkswap 设备文件名”就能够格式化该分区成为 swap 格式
  3. 使用:最后将该 swap 设备启动,方法为:“swapon 设备文件名”。
  4. 观察:最终通过 free 与 swapon -s 这个指令来观察一下内存的用量吧!

文件系统的特殊观察与操作

磁盘空间之浪费问题

整个文件系统中包括 superblock, inode table 与其他中介数据等其实都会浪费磁盘容量喔!

ls -l 第一行的 total 就是该目录下所有数据所使用的 *实际block数量 * block大小的值*

1
2
3
4
5
6
7
8
9
10
[root@study ~]$ ll -sh
total 12K
4.0K -rw-------. 1 root root 1.8K May 4 17:57 anaconda-ks.cfg
4.0K -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
0 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 crontab2 -&gt; /etc/crontab
4.0K -rw-r--r--. 1 root root 1.9K May 4 18:01 initial-setup-ks.cfg
0 -rw-r--r--. 1 root root 0 Jun 16 01:11 test1
0 drwxr-xr-x. 2 root root 6 Jun 16 01:11 test2
0 -rw-rw-r--. 1 root root 0 Jun 16 01:12 test3
0 drwxrwxr-x. 2 root root 6 Jun 16 01:12 test4

利用 GNU 的 parted 进行分区行为(Optional)

1
2
3
4
5
6
[root@study ~]# parted [设备] [指令 [参数]]
选项与参数:
指令功能:
新增分区:mkpart [primary&#124;logical&#124;extended] [ext4&#124;vfat&#124;xfs] 开始 结束
显示分区:print
删除分区:rm [partition]

可以使用man parted,或者是parted /dev/vda help mkpart去查询更详细的数据。