管理好自己的磁盘文件系统,每个分区不可太大也不能太小, 太大会造成磁盘容量的浪费,太小则会产生文件无法储存的困扰
制作文件系统,包括分区、格式化与挂载等
1、认识 Linux 文件系统
1.2 文件系统特性
1、磁盘分区完毕后 还需要进行格式化,之后操作系统才能够使用这个文件系统
因为每种操作系统所设置的文件属性 / 权限 并不相同, 为了存放这些文件所需的数据,因此就需要 将分区进行格式化,以成为操作系统能够利用的 文件系统格式(每种操作系统能够使用的文件系统并不相同:windows 操作系统是不会认识 Linux 的 Ext2)
2、将一个分区格式化为多个文件系统(LVM),也能够 将多个分区合成一个文件系统(LVM, RAID)
目前 在格式化时 不再说成针对分区来格式化了,可以称呼一个可被挂载的数据为 一个文件系统而不是一个分区
3、文件系统的运行 与操作系统的文件数据有关。文件数据 除了文件实际内容外, 通常含有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)
文件系统 通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,实际数据则放置到 data block 区块中。 另外,还有一个超级区块 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等
- superblock:记录此 filesystem 的整体信息,包括 inode / block 的总量、使用量、剩余量, 以及文件系统的格式与相关信息等
- inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
- block:实际记录文件的内容,若文件太大时,会占用多个 block
4、索引式文件系统
每个 inode 与 block 都有编号
文件系统先格式化出 inode 与 block 的区块,假设某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为 2, 7, 13, 15 这四个 block 号码,此时 操作系统就能够据此来排列磁盘的读取顺序,可以一口气将四个 block 内容读出来
5、U盘使用的文件系统一般为 FAT 格式。FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中
这个文件系统 没有办法一口气就知道四个 block 的号码,得要一个一个 将 block 读出后,才会知道下一个 block 在何处
6、需要磁盘重组的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差所致。 这个时候可以通过磁盘重组 将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易
Ext2 是索引式文件系统,基本上不太需要常常进行磁盘重组的
1.3 Linux 的 EXT2 文件系统(inode)
1、Linux 的文件除了原有的数据内容外,还含有非常多的权限与属性,这些权限与属性是为了保护每个使用者所拥有数据的隐密性,标准的 Linux 文件系统 Ext2 就是使用这种 inode 为基础的文件系统
2、文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动
3、文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block 的数量太庞大,不容易管理
Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统
在整体的规划当中,文件系统最前面有一个开机扇区(boot sector),这个开机扇区可以安装开机管理程序,如此一来 就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗磁盘唯一的 MBR, 这样也才能够制作出多重开机的环境
4、每一个区块群组(block group)的六个主要内容
data block (数据区块)
放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种
在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录
Ext2 文件系统的 block限制:
1)由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件大小并不相同
2)原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
3)每个 block 内最多只能够放置一个文件的数据;
4)如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
5)若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)
假设你的Ext2文件系统使用 4K block ,而该文件系统中有 10000 个小文件,每个文件大小均为 50Bytes, 请问此时你的磁盘浪费多少容量?
Ext2 文件系统中一个 block 仅能容纳一个文件,因此每个 block 会浪费“ 4096 - 50 = 4046 (Byte)”, 系统中总共有一万个小文件,所有文件大小为:50 (Bytes) x 10000 = 488.3KBytes,但此时浪费的容量为:“ 4046 (Bytes) x 10000 = 38.6MBytes ”
BBS 上面的数据使用的是纯文本来记载每篇留言,会产生很多小文件
是否就将 block 大小订为 1K 即可? 这也不妥,因为如果 block 较小的话,那么大型文件将会占用数量更多的 block ,而 inode 也要记录更多的 block 号码,此时将可能导致文件系统不良的读写性能
现在的磁盘容量都太大了,大概大家都只会选择 4K 的 block 大小
inode table (inode 表格)
inode 的内容 记录文件的属性 以及 该文件实际数据是放置在哪几号 block 内
inode 记录的文件数据至少有下面这些:
- 该文件的存取模式(read/write/excute);
- 该文件的拥有者与群组(owner/group);
- 该文件的容量;
- 该文件创建或状态改变的时间(ctime);
- 最近一次的读取时间(atime);
- 最近修改的时间(mtime);
- 定义文件特性的旗标(flag),如 SetUID…;
- 该文件真正内容的指向 (pointer)
inode 的数量与大小 也是在格式化时就已经固定了
- 每个 inode 大小均固定为 128 Bytes (新的 ext4 与 xfs 可设置到 256 Bytes);
- 每个文件都仅会占用一个 inode 而已;因此文件系统能够创建的文件数量与 inode 的数量有关;
- 系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容
inode 要记录的数据非常多,但偏偏又只有 128Bytes 而已, 而 inode 记录一个 block 号码要花掉 4Byte ,假设 一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万笔 block 号码的记录。inode 怎么记录这么多信息?
系统 将 inode 记录 block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区
直接块(Direct Blocks): 每个直接块包含文件数据的地址。Inode中有12个这样的直接块
一级间接块(Single Indirect Block): 该块中包含了指向数据块地址的指针列表。也就是说,这个块不是直接包含数据,而是包含指向其他数据块的指针
二级间接块(Double Indirect Block): 该块中包含了指向一级间接块的指针列表。也就是说,这个块包含的是指向指针列表的指针,而这些指针列表再指向实际的数据块
三级间接块(Triple Indirect Block): 该块中包含了指向二级间接块的指针列表。也就是说,这个块包含的是指向包含指针列表的指针列表的指针,而这些指针列表再指向一级间接块的指针列表,最终指向实际的数据块
inode 能够指定多少个 block 呢?以较小的 1K block 来说明
12 个直接指向: 12*1K=12K 由于是直接指向,所以总共可记录 12 笔记录
间接: 256 * 1K = 256 K
每笔 block 号码的记录会花去 4Bytes,因此 1K 的大小能够记录 256 笔记录
双间接: 256 * 256 * 1K = 256^2 K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上;
三间接: 256 * 256 * 256 * 1K = 256^3 K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个号码
总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256 * 256 + 256 * 256 * 256 (K) = 16 GB
当文件系统 将 block 格式化为 1K 大小时,能够容纳的最大文件为 16GB,比较一下文件系统限制表的结果可发现是一致的。但这个方法不能用在 2K 及 4K block 大小的计算中, 因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合
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
一般来说, superblock 的大小为 1024Bytes,每个 block group 都可能含有 superblock,一个文件系统应该仅有一个 superblock
除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock(主要是做为第一个 block group 内 superblock 的备份)
Filesystem Description (文件系统描述说明)
描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap, inodetable, data block) 分别介于哪一个 block 号码之间
block bitmap (区块对照表)
从 block bitmap 当中可以知道 哪些 block 是空的,因此 系统就能够很快速的找到 可使用的空间来处置文件
inode bitmap (inode 对照表)
与 block bitmap 是类似的功能,inode bitmap 记录使用与未使用的 inode 号码
dumpe2fs: 查询 Ext 家族 superblock 信息的指令
每个区段与 superblock 的信息都可以使用 dumpe2fs 这个指令来查询
dumpe2fs [-bh] 设备文件名
选项与参数:
-b :列出保留为坏轨的部分
-h :仅列出 superblock 的数据,不会列出其他的区段内容
范例:一块 1GB ext4 文件系统内容
blkid # 这个指令可以叫出目前系统有被格式化的设备
/dev/vda1: LABEL="myboot" UUID="ce4dbf1b-2b3d-4973-8234-73768e8fd659" TYPE="xfs"
/dev/vda2: LABEL="myroot" UUID="21ad8b9a-aaad-443c-b732-4e2522e95e23" TYPE="xfs"
/dev/vda3: UUID="12y99K-bv2A-y7RY-jhEW-rIWf-PcH5-SaiApN" TYPE="LVM2_member"
/dev/vda5: UUID="e20d65d9-20d4-472f-9f91-cdcfb30219d6" TYPE="ext4" // ext4
dumpe2fs /dev/vda5
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name: <none> # 文件系统的名称(不一定会有)
Last mounted on: <not available> # 上一次挂载的目录位置
Filesystem UUID: e20d65d9-20d4-472f-9f91-cdcfb30219d6
Filesystem magic number: 0xEF53 # 上方的 UUID 为 Linux 对设备的定义码
Filesystem revision #: 1 (dynamic) # 下方的 features 为文件系统的特征数据
Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit
flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl # 默认在挂载时会主动加上的挂载参数
Filesystem state: clean # 这块文件系统的状态为何,clean 是没问题
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 65536 # inode 的总数
Block count: 262144 # block 的总数
Reserved block count: 13107 # 保留的 block 总数
Free blocks: 249189 # 还有多少的 block 可用数量
Free inodes: 65525 # 还有多少的 inode 可用数量
First block: 0
Block size: 4096 # 单个 block 的容量大小
Fragment size: 4096
Group descriptor size: 64
....(中间省略)....
Inode size: 256 # inode 的容量大小!已经是 256 了喔!
....(中间省略)....
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 3c2568b4-1a7e-44cf-95a2-c8867fb19fbc
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M # Journal 日志式数据的可供纪录总容量
Journal length: 8192
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 0-32767) # 第一块 block group 位置
Checksum 0x13be, unused inodes 8181
Primary superblock at 0, Group descriptors at 1-1 # 主要 superblock 的所在
Reserved GDT blocks at 2-128
Block bitmap at 129 (+129), Inode bitmap at 145 (+145)
Inode table at 161-672 (+161) # inode table 的所在
28521 free blocks, 8181 free inodes, 2 directories, 8181 unused inodes
Free blocks: 142-144, 153-160, 4258-32767 # 下面两行说明剩余的容量有多少
Free inodes: 12-8192
Group 1: (Blocks 32768-65535) [INODE_UNINIT] # 后续为更多其他的 block group
....(下面省略)....
# 前半部显示 supberblock 的内容,包括标头名称(Label)以及inode/block的相关信息
# 后面则是每个 block group 的个别信息,可以看到各区段数据所在的号码
# 也就是说,基本上所有的数据还是与 block 的号码有关
1.4 与目录树的关系
每个文件(不管是一般文件还是目录文件)都会占用一个 inode , 且可依据文件内容的大小来分配多个 block 给该文件使用
目录的内容在记录文件名, 一般文件才是实际记录数据内容的地方
1.4.1 目录
在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录
inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码; 而 block 则是记录在这个目录下的文件名 与 该文件名占用的 inode 号码数据。也就是说 目录所占用的 block 内容在记录如下的信息
想要实际观察 root 主文件夹内的文件所占用的 inode 号码时,可以使用 ls -i 这个选项来处理:
使用“ ll / ”时,出现的目录几乎都是 1024 的倍数
ll -d / /boot /usr/sbin /proc /sys
dr-xr-xr-x. 17 root root 4096 May 4 17:56 / # 1 个 4K block
dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot # 1 个 4K block
dr-xr-xr-x. 155 root root 0 Jun 15 15:43 /proc # 这两个为内存内数据,不占磁盘容量
dr-xr-xr-x. 13 root root 0 Jun 15 23:43 /sys
dr-xr-xr-x. 2 root root 16384 May 4 17:55 /usr/sbin # 4 个 4K block,由于 /usr/sbin 的内容比较复杂
在目录下面的文件数如果太多 而导致一个 block 无法容纳的下所有的文件名与 inode 对照表时,Linux 会给予该目录多一个 block 来继续记录相关的数据
1.4.2 文件
ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小的 block 数量给该文件
1.4.3 目录树读取
1、inode 本身并不记录文件名,文件名的记录是在目录的 block 当中
当我们要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据
2、 /etc/passwd 有关的目录读取流程
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
- / 的 inode: 通过挂载点的信息找到 inode 号码为 128 的根目录 inode,且 inode 规范的权限 让我们可以读取该 block 的内容(有 r 与 x)
- / 的 block: 经过上个步骤取得 block 的号码,并找到该内容有 etc/ 目录的 inode 号码 (33595521)
- etc/ 的 inode: 读取 33595521 号 inode 得知 使用者 具有 r 与 x 的权限,因此可以读取 etc/ 的 block 内容
- etc/ 的 block: 经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 (36628004)
- passwd 的 inode: 读取 36628004 号 inode 得知 使用者 具有 r 的权限,因此可以读取 passwd 的 block 内容
- passwd 的 block: 最后将该 block 内容的数据读出来
3、ext2 在 inode 处已经将该文件所记录的 block 号码都记上了, 所以数据可以一次性读取,但是如果文件真的太过离散,还是会发生读取效率低的问题
因为磁头还是得要在整个文件系统中来来去去的频繁读取:整个 filesystem 内的数据全部复制出来,将该 filesystem 重新格式化, 再将数据给他复制回去
1.5 EXT2/EXT3/EXT4 文件的存取与日志式文件系统的功能
1、新建一个文件或目录时,文件系统的行为是:
先确定使用者对于欲新增文件的目录是否具有 w 与 x 的权限,若有的话才能新增;
根据 inode bitmap 找到没有使用的 inode 号码,并将新文件的权限/属性写入;
根据 block bitmap 找到没有使用中的 block 号码,并将实际的数据写入 block 中,且更新 inode 的 block 指向数据;
将刚刚写入的 inode 与 block 数据同步更新 inode bitmap 与 block bitmap,并更新 superblock 的内容
2、将 inode table 与 data block 称为数据存放区域,至于其他 例如 superblock、 block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据)
3、数据的不一致状态:文件在写入文件系统时,因为不知名原因导致系统中断,写入的数据仅有 inode table 及 data block 而已, 最后一个同步更新中介数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存放区产生不一致
早期的 Ext2 文件系统中,如果发生这个问题, 那么系统在重新开机的时候,就会借由 Superblock 当中记录的 valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查
这样的检查真的是很费时,因为要针对 metadata 区域与实际数据存放区来进行比对
4、日志式文件系统
如果在 filesystem 当中规划出一个区块,该区块专门 记录写入或修订文件时的步骤
预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录
万一数据的纪录过程当中发生了问题,那么 系统只要去检查日志记录区块, 就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块 filesystem 去检查
1.6 Linux 文件系统的运行
1、磁盘写入的速度要比内存慢很多, 因此你会常常耗在等待磁盘的写入/读取上
非同步处理
当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设置为干净(clean)的。 但如果内存中的文件数据被更改过了,此时该内存中的数据会被设置为脏的 (Dirty)
此时所有的动作都还在内存中执行,并没有写入到磁盘中。系统会不定时的将内存中设置为“Dirty”的数据写回磁盘,以保持磁盘与内存数据的一致性。 也可以利用第四章谈到的 sync指令来手动强迫写入磁盘
2、将常用的文件放置到内存当中,就会增加系统性能
系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写。因此 Linux 的实体内存最后都会被用光,这是正常的情况
若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)
1.7 挂载点的意义 (mount point)
1、每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用
挂载点一定是目录,该目录为进入该文件系统的入口。 因此并不是你有任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,才能够使用该文件系统的
三个挂载点,分别是 /, /boot, /home 三个
ls -lid / /boot /home
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
128 dr-xr-xr-x. 4 root root 4096 May 4 17:59 /boot
128 drwxr-xr-x. 5 root root 41 Jun 17 00:20 /home
/:这是根文件系统,系统启动时第一个挂载的文件系统。通常包含所有核心操作系统文件。
/boot:这个目录通常用于存放引导加载程序的文件,可能是一个单独的文件系统挂载在/boot上。
/home:这个目录通常用于存放用户的主目录,可能是一个单独的文件系统挂载在/home上
dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
| | | | | | | | |
| | | | | | | | +-- 文件或目录名称
| | | | | | | +------------------ 最后修改时间
| | | | | | +------------------------ 文件大小
| | | | | +----------------------------- 所属组
| | | | +---------------------------------- 所有者
| | | +-------------------------------------- 硬链接数
| | +----------------------------------------- 文件权限(其他用户)
| +-------------------------------------------- 文件权限(所属组)
+----------------------------------------------- 文件权限(所有者)
由于 XFS filesystem 最顶层的目录之 inode 一般为 128 号,因此可以发现 /, /boot, /home 为三个不同的 filesystem
每个文件系统都有自己的inode表,inode号在每个文件系统内是唯一的,但不同文件系统之间可以重复
2、根目录下的 . 与 … 是相同的东西
同一个 filesystem 的某个 inode 只会对应到一个文件内容(因为一个文件占用一个 inode), 因此 可以通过判断 inode 号码来确认不同文件名是否为相同的文件
ls -ild / /. /..
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /.
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /..
1.8 其他 Linux 支持的文件系统与 VFS
1、Linux 的标准文件系统是 ext2 ,且还有增加了日志功能的 ext3/ext4
速度很快的日志式文件系统,包括 SGI 的 XFS 文件系统, 可以适用更小型文件的 Reiserfs 文件系统,以及 Windows 的 FAT 文件系统等等
2、Linux VFS
Linux 的核心 如何管理这些认识的文件系统:整个 Linux 的系统 都是通过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。 整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理
通过 VFS 的功能来管理所有的 filesystem, 省去 需要自行设置读取文件系统的定义
1.9 XFS 文件系统简介
1、EXT 家族 较伤脑筋的地方:支持度最广,但格式化超慢,采用的是预先规划出所有的 inode/block/meta data 等数据,未来系统可以直接取用, 不需要再进行动态配置
TB 以上等级的传统 ext 家族文件系统在格式化的时候,光是系统要预先分配 inode 与 block 就消耗很多时间
2、XFS 文件系统的配置
被开发来用于大容量磁盘以及高性能文件系统
xfs 文件系统在数据的分布上,主要规划为三个部份,一个数据区 (data section)、一个文件系统活动登录区 (log section)以及一个实时运行区 (realtime section)
-
数据区 就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock 等数据,也是分为多个储存区群组来分别放置文件系统所需要的数据
每个储存区群组都包含了
(1)整个文件系统的 superblock
(2)剩余空间的管理机制
(3)inode的分配与追踪
此外,inode与 block 都是系统需要用到时, 这才动态配置产生,所以格式化动作超级快
xfs 的这个数据区的储存区群组,就将它想成是 ext 家族的 block 群组 (block groups) 。只是 inode 与 block 是动态产生,并非一开始于格式化就完成配置的 -
文件系统活动登录区:被用来纪录文件系统的变化,有点像日志区,文件的变化会在这里纪录下来,直到该变化完整的写入到数据区后, 该笔纪录才会被终结。如果文件系统因为某些缘故 (例如最常见的停电) 而损毁时,系统会拿这个登录区块来进行检验,看看系统挂掉之前, 文件系统正在运行些啥动作,借以快速的修复文件系统
因为系统所有动作的时候都会在这个区块做个纪录,因此这个区块的磁盘活动是相当频繁。xfs 设计有趣,在这个区域中, 你可以指定外部的磁盘 来作为 xfs 文件系统的日志区块 -
实时运行区:当有文件要被创建时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到 data section 的 inode 与 block 去
这个 extent 区块的大小得要在格式化的时候就先指定,最小值是 4K 最大可到 1G。一般非磁盘阵列的磁盘默认为 64K 容量,而具有类似磁盘阵列的 stripe 情况下,则建议 extent 设置为与 stripe 一样大较佳。这个 extent 最好不要乱动,因为可能会影响到实体磁盘的性能
2、文件系统的简单操作
要知道 如何查询整体文件系统的总容量 与 每个目录所占用的容量
2.1 磁盘与目录的容量
1、磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的
- df:列出文件系统的整体磁盘使用量;
df [-ahikHTm] [目录或文件名]
选项与参数:
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;(系统里面其实还有很多特殊的文件系统存在的。那些比较特殊的文件系统几乎都是在内存当中,例如 /proc 这个挂载点)
-k :以 KBytes 的容量显示各文件系统;
-m :以 MBytes 的容量显示各文件系统;
-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H :以 M=1000K 取代 M=1024K 的进位方式;
-T :连同该 partition 的 filesystem 名称 (例如 xfs) 也列出;
-i :不用磁盘容量,而以 inode 的数量来显示
在 Linux 下面如果 df 没有加任何选项,那么默认会将系统内所有的(不含特殊内存内的文件系统与 swap) 都以 1 KBytes 的容量来列出来
范例二:将容量结果以易读的容量格式显示出来
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
devtmpfs 613M 0 613M 0% /dev
tmpfs 623M 80K 623M 1% /dev/shm
tmpfs 623M 25M 599M 4% /run
tmpfs 623M 0 623M 0% /sys/fs/cgroup
/dev/mapper/centos-home 5.0G 67M 5.0G 2% /home
/dev/vda2 1014M 131M 884M 13% /boot
# 不同于范例一,这里会以 G/M 等容量格式显示出来,比较容易看
范例四:将 /etc 下面的可用的磁盘容量以易读的容量格式显示
df -h /etc
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 10G 3.3G 6.8G 33% /
特殊文件系统是操作系统用来提供一些系统信息和接口的虚拟文件系统。它们不像传统的文件系统那样存储在磁盘上,而是动态生成和维护在内存中
/proc 是一个非常重要的虚拟文件系统,它提供了关于系统和进程的信息。它是一个伪文件系统,通常被称为进程文件系统(Process File System)。每当你访问 /proc 下的文件时,操作系统会实时生成这些文件的内容
df 主要读取的数据几乎都是针对一整个文件系统,因此读取的范围主要是在 Superblock 内的信息, 所以这个指令显示结果的速度非常的快速
如果使用 -a 这个参数时,系统会出现 /proc 这个挂载点,但是里面的东西都是 0 , /proc 的东西都是 Linux 系统所需要载入的系统数据,而且是挂载在“内存当中”的, 所以当然没有占任何的磁盘空间
- du:评估文件系统的磁盘使用量(常用在推估目录所占容量)
du [-ahskm] 文件或目录名称
选项与参数:
-a :列出所有的文件与目录容量,因为默认仅统计目录下面的文件量而已。
-h :以人们较易读的容量格式 (G/M) 显示;
-s :列出总量而已,而不列出每个各别的目录占用容量;
-S :不包括子目录下的总计,与 -s 有点差别。
-k :以 KBytes 列出容量显示;
-m :以 MBytes 列出容量显示;
范例一:列出目前目录下的所有文件大小
du
4 ./.cache/dconf <==每个目录都会列出来
4 ./.cache/abrt
8 ./.cache
....(中间省略)....
0 ./test4
4 ./.ssh # 包括隐藏文件的目录
76 . # 这个目录(.)所占用的总量
直接输入 du 没有加任何选项时,则 du 会分析 “目前所在目录” 的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件)
因此,目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量输出的数值数据为 1K 大小的容量单位
du -sm /*
0 /bin
198 /boot
1 /cdrom
0 /dev
12 /etc
13205 /home
0 /lib
0 /lib32
0 /lib64
0 /libx32
1 /lost+found
2743 /media
1 /mnt
1 /opt
du: 无法访问 '/proc/65734/task/65734/fd/4': 没有那个文件或目录
du: 无法访问 '/proc/65734/task/65734/fdinfo/4': 没有那个文件或目录
du: 无法访问 '/proc/65734/fd/3': 没有那个文件或目录
du: 无法访问 '/proc/65734/fdinfo/3': 没有那个文件或目录
0 /proc
6385 /root
du: 无法访问 '/run/user/1000/doc': 权限不够
du: 无法访问 '/run/user/1000/gvfs': 权限不够
2 /run
0 /sbin
4669 /snap
1 /srv
2049 /swapfile
0 /sys
1 /tmp
6381 /usr
2604 /var
利用万用字符 * 来代表每个目录,如果想要检查某个目录下,哪个次目录占用最大的容量,可以用这个方法找出来。值得注意的是,如果刚刚安装好 Linux 时,那么整个系统容量最大的应该是 /usr 。而 /proc 虽然有列出容量,但是那个容量是在内存中,不占磁盘空间。至于 /proc 里头会列出一堆“No such file or directory” 的错误,因为是内存内的程序,程序执行结束就会消失,因此会有些目录找不到
与 df 不一样的是,du 这个指令其实会直接到文件系统内去搜寻所有的文件数据, 所以上述第三个范例指令的运行会执行一小段时间
-S ,由于 du 默认 会将所有文件的大小均列出,因此假设 在 /etc 下面使用 du 时, 所有的文件大小,包括 /etc 下面的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次, 因此 会误会 du 分析的结果不太对劲。如果想要列出某目录下的全部数据, 或许也可以加上 -S 的选项,减少次目录的加总
2.2 实体链接与符号链接: ln
1、在 Linux 下面的链接文件有两种
一种是 类似 Windows 的捷径功能的文件,可以让你快速的链接到目标文件(或目录)(软连接)
另一种 则是通过文件系统的 inode 链接来产生新文件名,而不是产生新文件,这种称为实体链接 (硬连接)
Hard Link (实体链接, 硬式链接或实际链接)
1)每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;
2)想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取
其实文件名只与目录有关,但是文件内容则与 inode 有关。有没有可能有多个文件名对应到同一个 inode 号码呢?有的!那就是 hard link 的由来。 所以简单的说:hard link 只是在某个目录下新增一笔文件名链接到某 inode 号码的关连记录而已
如果 将任何一个“文件名”删除,其实 inode 与 block 都还是存在的,此时 可以通过另一个“文件名”来读取到正确的文件数据。此外,不论使用哪个“文件名”来编辑, 最终的结果 都会写入到相同的 inode 与 block 中,因此均能进行数据的修改
hard link 只是在某个目录下的 block 多写入一个关连数据而已,既不会增加 inode 也不会耗用 block 数量
hard link 的限制:
不能跨 Filesystem
不能 link 目录
因为如果使用 hard link 链接到目录时, 链接的数据 需要连同被链接目录下面的所有数据都创建链接
如果你要将 /etc 使用实体链接创建一个 /etc_hd 的目录时,那么在 /etc_hd 下面的所有文件名同时都与 /etc 下面的文件名要创建 hard link 的,而不是仅链接到 /etc_hd 与 /etc 而已。 并且,未来如果需要在 /etc_hd 下面创建新文件时,连带的, /etc 下面的数据又得要创建一次 hard link ,因此造成环境相当大的复杂度
ll -i /etc/crontab
34474855 -rw-r--r--. 1 root root 451 Jun 10 2014 /etc/crontab
ln /etc/crontab . # 创建实体链接的指令
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
# 第3栏的链接数也会增加
Symbolic Link (符号链接,亦即是捷径)
Symbolic link 就是在创建一个独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的文件名,会占用掉 inode 与 block
inode 读取到链接文件的内容仅有文件名,根据文件名链接到正确的目录去取得目标文件的 inode , 最终就能够读取到正确的数据了
由于只是利用文件来做为指向的动作, 所以,当来源文件被删除之后,symbolic link 的文件会“开不了”
ln -s /etc/crontab crontab2
ll -i /etc/crontab /root/crontab2
34474855 -rw-r--r--. 2 root root 451 Jun 10 2014 /etc/crontab
53745909 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 /root/crontab2 -> /etc/crontab
两个文件指向不同的 inode 号码,是两个独立的文件
链接文件的重要内容 就是 会写上目标文件的“文件名”, 可以发现 为什么上表中链接文件的大小为 12 Bytes —— 因为箭头(–>)右边的文件名“/etc/crontab”总共有 12 个英文,每个英文占用 1 个 Bytes ,所以文件大小就是 12Bytes
ln [-sf] 来源文件 目标文件
选项与参数:
-s :如果不加任何参数就进行链接,那就是hard link,至于 -s 就是symbolic link
-f :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建
将 /etc/passwd 复制到 /tmp 下面,并且观察 inode 与 block
将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件,并观察文件与容量
即使多了一个文件在 /tmp 下面,整个 inode 与 block 的容量并没有改变
将 /tmp/passwd 创建一个符号链接
passwd-so 指向的 inode number 不同,这是一个新的文件~这个文件的内容是指向 passwd 的。passwd-so 的大小是 6Bytes ,因为 “passwd” 这个单字共有六个字符之故
范例四:删除原始文件 passwd ,其他两个文件是否能够打开?
rm passwd
cat passwd-hd
.....(正常显示完毕!)
cat passwd-so
cat: passwd-so: No such file or directory
ll passwd*
-rw-r--r--. 1 root root 2092 Jun 17 00:20 passwd-hd
lrwxrwxrwx. 1 root root 6 Jun 23 22:40 passwd-so -> passwd
如果 ln 使用 -s 的参数时,就做成 Windows 下面的“捷径”的意思。当修改 Linux 下的 symbolic link 文件时,则更动的其实是“原始文件”, 所以不论原始文件被链接到哪里去,只要你修改了链接文件,原始文件就跟着变
2、关于目录的 link 数量:建目录时,他默认的 link 数量会是2,一个“空目录”里面至少会存 . 与 … 这两个目录
当创建一个新目录名称为 /tmp/testing 时,基本上会有三个东西:
/tmp/testing
/tmp/testing/.
/tmp/testing/…
而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的,而 /tmp/testing/… 则代表 /tmp 这个目录,新的目录的 link 数为 2 ,而上层目录的 link 数则会增加 1
3、磁盘的分区、格式化、检验与挂载
1、在系统里面新增一颗磁盘时:
1)对磁盘进行分区,以创建可用的 partition ;
2)对该 partition 进行格式化 (format),以创建系统可用的 filesystem;
3)若想要仔细一点,则可对刚刚创建好的 filesystem 进行检验;
4)在 Linux 系统上,需要创建挂载点 (亦即是目录),并将他挂载上来;
3.1 观察磁盘分区状态
1、磁盘分区主要有 MBR 以及 GPT 两种格式,这两种格式所使用的分区工具不太一样
2、lsblk(list block device) 列出系统上的所有磁盘列表
lsblk [-dfimpt] [device]
选项与参数:
-d :仅列出磁盘本身,并不会列出该磁盘的分区数据
-f :同时列出该磁盘内的文件系统名称
-i :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用)
-m :同时输出该设备在 /dev 下面的权限数据 (rwx 的数据)
-p :列出该设备的完整文件名!而不是仅列出最后的名字而已。
-t :列出该磁盘设备的详细数据,包括磁盘伫列机制、预读写的数据量大小等
列出本系统下的所有磁盘与磁盘内的分区信息
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 40G 0 disk # 一整颗磁盘
|-vda1 252:1 0 2M 0 part
|-vda2 252:2 0 1G 0 part /boot
|-vda3 252:3 0 30G 0 part
|-centos-root 253:0 0 10G 0 lvm / # 在 vda3 内的其他文件系统
|-centos-swap 253:1 0 1G 0 lvm [SWAP]
|-centos-home 253:2 0 5G 0 lvm /home
目前的系统主要有个 sr0 以及一个 vda 的设备,而 vda 的设备下面又有三个分区, 其中 vda3 甚至还有因为 LVM 产生的文件系统
NAME:就是设备的文件名,会省略 /dev 等前导目录(在路径中位于文件或目录名称前面的目录部分)
MAJ:MIN:核心认识的设备都是通过这两个代码来熟悉的,分别是主要:次要设备代码
RM:是否为可卸载设备 (removable device),如光盘、USB 磁盘等等
SIZE:容量
RO:是否为只读设备
TYPE:是磁盘 (disk)、分区 (partition) 还是只读存储器 (rom) 等输出
MOUTPOINT:挂载点
3、blkid 列出设备的 UUID 等参数
UUID 是全域单一识别码 (universally unique identifier),Linux 会将系统内所有的设备都给予一个独一无二的识别码, 这个识别码 就可以拿来作为 挂载或者是使用这个设备/文件系统
4、parted 列出磁盘的分区表类型与分区信息
不清楚磁盘的分区类型。可以通过简单的 parted 来输出:parted device_name print
列出 /dev/vda 磁盘的相关数据
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
3.2 磁盘分区: gdisk/fdisk
1、MBR 分区表 使用 fdisk 分区, GPT 分区表 使用 gdisk 分区 gdisk 设备名称
通过 lsblk 或 blkid 先找到磁盘,再用 parted /dev/xxx print 来找出内部的分区表类型,之后才用 gdisk 或 fdisk 来操作系统
由前一小节的 lsblk 输出,我们知道系统有个 /dev/vda,请观察该磁盘的分区与相关数据
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): #这里可以让你输入指令动作,可以按问号 (?) 来查看可用指令
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):
只要离开 gdisk 时按下“q”,那么所有的动作“都不会生效”,相反的, 按下“w”就是动作生效的意思,“ p ”可以列出 目前这颗磁盘的分区表信息
现在的分区主要是以扇区为最小的单位
Command (? for help): p # 这里可以输出目前磁盘的状态
Disk /dev/vda: 83886080 sectors, 40.0 GiB # 磁盘文件名/扇区数与总容量
Logical sector size: 512 Bytes # 单一扇区大小为 512 Bytes
Disk identifier (GUID): A4C3C813-62AF-4BFE-BAC9-112EBD87A483 # 磁盘的 GPT 识别码
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 83886046
Partitions will be aligned on 2048-sector boundaries
Total free space is 18862013 sectors (9.0 GiB)
Number Start (sector) End (sector) Size Code Name # 下面为完整的分区信息了!
1 2048 6143 2.0 MiB EF02 # 第一个分区数据
2 6144 2103295 1024.0 MiB 0700
3 2103296 65026047 30.0 GiB 8E00
# 分区编号 开始扇区号码 结束扇区号码 容量大小
Command (? for help): q
Number:分区编号,1 号指的是 /dev/vda1 这样计算
Start (sector):每一个分区的开始扇区号码位置
End (sector):每一个分区的结束扇区号码位置,与 start 之间可以算出分区的总容量
Size:就是分区的容量了
Code:在分区内的可能的文件系统类型。Linux 为 8300,swap 为 8200。不过这个项目只是一个提示而已,不见得真的代表此分区内的文件系统
Name:文件系统的名称等等
从上表我们可以发现几件事情:
整部磁盘还可以进行额外的分区,因为最大扇区为 83886080,但只使用到 65026047 号而已;
分区的设计中,新分区通常选用上一个分区的结束扇区号码数加 1 作为起始扇区号码
这个 gdisk 只有 root 才能执行
使用的“设备文件名”不要加上数字,因为 partition 是针对“整个磁盘设备”而不是某个 partition ,所以执行“ gdisk /dev/vda1 ” 就会发生错误
2、用 gdisk 新增分区
gdisk /dev/vda
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
1 2048 6143 2.0 MiB EF02
2 6144 2103295 1024.0 MiB 0700
3 2103296 65026047 30.0 GiB 8E00
# 找出最后一个 sector 的号码
Command (? for help): n # 开始新增的行为
Partition number (4-128, default 4): 4 # 默认就是 4 号,所以也能 enter 即可
First sector (34-83886046, default = 65026048) or {+-}size{KMGTP}: 65026048 # 也能 enter
Last sector (65026048-83886046, default = 83886046) or {+-}size{KMGTP}: +1G # 决不要 enter,默认值会将所有的容量用光
# 不需要自己去计算扇区号码,通过 +容量 的这个方式,
# 就可以让 gdisk 主动去帮你算出最接近你需要的容量的扇区号码
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): # 使用默认值即可~直接 enter 下去
# 这里在让你选择未来这个分区预计使用的文件系统,默认都是 Linux 文件系统的 8300
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
1 2048 6143 2.0 MiB EF02
2 6144 2103295 1024.0 MiB 0700
3 2103296 65026047 30.0 GiB 8E00
4 65026048 67123199 1024.0 MiB 8300 Linux filesystem
文件系统的 ID, Linux 大概都是 8200/8300/8e00 等三种格式, Windows 几乎都用 0700,如果忘记这些数字,可以在 gdisk 内按下:“ L ”来显示
Command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/vda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
# gdisk 会先警告你可能的问题,我们确定分区是对的,这时才按下 y
# 因为这颗磁盘目前正在使用当中,因此系统无法立即载入新的分区表
cat /proc/partitions
major minor #blocks name
252 0 41943040 vda
252 1 2048 vda1
252 2 1048576 vda2
252 3 31461376 vda3
253 0 10485760 dm-0
253 1 1048576 dm-1
253 2 5242880 dm-2
# 并没有 vda4, vda5, vda6,因为核心还没有更新
因为 Linux 此时还在使用这颗磁盘,为了担心系统出问题,所以分区表并没有被更新
有两个方式可以来处理:其中一个是重新开机,另外一个则是通过 partprobe 这个指令来处理
3、partprobe 更新 Linux 核心的分区表信息
partprobe [-s] # 你可以不要加 -s ,那么屏幕不会出现讯息
partprobe -s # 不过还是建议加上 -s 比较清晰
/dev/vda: gpt partitions 1 2 3 4 5 6
cat /proc/partitions # 核心的分区纪录
major minor #blocks name
252 0 41943040 vda
252 1 2048 vda1
252 2 1048576 vda2
252 3 31461376 vda3
252 4 1048576 vda4
252 5 1048576 vda5
252 6 512000 vda6
4、用 gdisk 删除一个分区
gdisk /dev/vda
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
1 2048 6143 2.0 MiB EF02
2 6144 2103295 1024.0 MiB 0700
3 2103296 65026047 30.0 GiB 8E00
4 65026048 67123199 1024.0 MiB 8300 Linux filesystem
5 67123200 69220351 1024.0 MiB 0700 Microsoft basic data
6 69220352 70244351 500.0 MiB 8200 Linux swap
Command (? for help): d
Partition number (1-6): 6
Command (? for help): p
# /dev/vda6 不见了
lsblk
# 还是有 /dev/vda6,还没有更新核心的分区表
partprobe -s
lsblk
# 这个时候,那个 /dev/vda6 才真的消失不见了
不要去处理一个正在使用中的分区,例如,我们的系统现在已经使用了 /dev/vda2 ,那如果你要删除 /dev/vda2 的话, 必须要先将 /dev/vda2 卸载,否则直接删除该分区的话,虽然磁盘还是会写入正确的分区信息,但是核心会无法更新分区表的信息的
5、fdisk
fdisk 有时会使用柱面作为分区的最小单位,与 gdisk 默认使用 扇区 不太一样
MBR 分区是有限制的 (Primary, Extended, Logical…)跟 gdisk 使用的方式,只是一个使用 ? 作为指令提示数据,一个使用 m 作为提示
fdisk /dev/sda
Command (m for help): m # 输入 m 后,就会看到下面这些指令介绍
Command action
d delete a partition #删除一个partition
n add a new partition #新增一个partition
p print the partition table #在屏幕上显示分区表
q quit without saving changes #不储存离开fdisk程序
w write table to disk and exit #将刚刚的动作写入分区表
3.3 磁盘格式化(创建文件系统)
1、分区完毕后 要进行文件系统的格式化。“make filesystem, mkfs” 指令其实是个综合的指令,会去调用正确的文件系统格式化工具软件
2、XFS 文件系统 mkfs.xfs
“格式化”其实应该称为“创建文件系统”
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|1]:log 设备是否为内置?默认为 1 内置,如果要用外部设备,使用下面设置
logdev=device :log 设备为后面接的那个设备上头的意思,需设置 internal=0 才可!
size=数值 :指定这块登录区的容量,通常最小得要有 512 个 block,大约 2M 以上才行!
-L :后面接这个文件系统的标头名称 Label name 的意思!
-r :指定 realtime section 的相关设置值,常见的有:
extsize=数值 :就是那个重要的 extent 数值,一般不须设置,但有 RAID 时,
最好设置与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。
范例:将前一小节分区出来的 /dev/vda4 格式化为 xfs 文件系统
mkfs.xfs /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=4, agsize=65536 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
# 很快格是化完毕!都用默认值!较重要的是 inode 与 block 的数值
blkid /dev/vda4
/dev/vda4: UUID="39293f4f-627b-4dfd-a015-08340537709c" TYPE="xfs"
# 确定创建好 xfs 文件系统了
xfs 可以使用多个数据流来读写系统,以增加速度,因此那个 agcount 可以跟 CPU 的核心数来做搭配
范例:找出你系统的 CPU 数,并据以设置你的 agcount 数值
grep 'processor' /proc/cpuinfo
processor : 0
processor : 1
# 所以就是有两颗 CPU 的意思
mkfs.xfs -f -d agcount=2 /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=2, agsize=131072 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
.....(下面省略).....
3、XFS 文件系统 for RAID 性能优化
磁盘阵列(RAID)是多颗磁盘组成一颗大磁盘的意思, 利用同步写入到这些磁盘的技术,不但可以加快读写速度,还可以让某一颗磁盘坏掉时,整个文件系统还是可以持续运行的状态
通过将文件先细分为数个小型的分区区块 (stripe) 之后,然后将众多的 stripes 分别放到磁盘阵列里面的所有磁盘
将众多的 stripes 分别放到磁盘阵列里面的所有磁盘, 所以一个文件是被同时写入到多个磁盘去,性能会好
为了文件的保全性,在这些磁盘里面,会保留数个 (与磁盘阵列的规划有关) 备份磁盘 (parity disk), 以及可能会保留一个以上的备用磁盘 (spare disk),对于数据的保全会比较有保障
分区区块 stripe 的数值大多介于 4K 到 1M 之间
当系统大多是大型文件时,stripe 可以设置大一些,这样磁盘阵列读/写的频率会降低,性能会提升
文件系统的读写 最好能够搭配磁盘阵列的参数来设计,可以先在 文件系统就将 stripe 规划好, 那交给 RAID 去存取时,它就 无须重复进行文件的 stripe 过程,性能当然会更好
假设个环境:
有两个线程的 CPU 数量,所以 agcount 最好指定为 2
当初设置 RAID 的 stripe 指定为 256K 这么大,因此 su 最好设置为 256k
设置的磁盘阵列有 8 颗,因为是 RAID5 的设置,所以有一个 parity (备份碟),因此指定 sw 为 7
由上述的数据中,可以发现数据宽度 (swidth) 应该就是 256K*7 得到 1792K,可以指定 extsize 为 1792k
mkfs.xfs -f -d agcount=2,su=256k,sw=7 -r extsize=1792k /dev/vda4
meta-data=/dev/vda4 isize=256 agcount=2, agsize=131072 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=64 swidth=448 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=64 blks, lazy-count=1
realtime =none extsz=1835008 blocks=0, rtextents=0
agcount 没啥问题, sunit 结果是 64 个 block,因为每个 block 为 4K,所以算出来容量就是 256K 也没错。那个 swidth 也相同,使用 448 * 4K 得到 1792K;那个 extsz 则是算成 Bytes 的单位,换算结果也没错
如果使用 sunit 与 swidth 直接套用在 mkfs.xfs 当中呢?那得小心了,因为指令中的这两个参数用的 是“几个 512Bytes 的 sector 数量”(结果是显示几个block) 的意思,是“数量”单位而不是“容量”单位。因此先计算为:
sunit = 256K/512Byte*1024(Bytes/K) = 512 个 sector
swidth = 7 个磁盘 sunit = 7 * 512 = 3584 个 sector
mkfs.xfs -f -d agcount=2,sunit=512,swidth=3584 -r extsize=1792k /dev/vda4
4、EXT4 文件系统 mkfs.ext4
mkfs.ext4 [-b size] [-L label] 设备名称
选项与参数:
-b :设置 block 的大小,有 1K, 2K, 4K 的容量,
-L :后面接这个设备的标头名称。
范例:将 /dev/vda5 格式化为 ext4 文件系统
mkfs.ext4 /dev/vda5
5、其他文件系统 mkfs
当我们使用 mkfs -t xfs 时,它就会跑去找 mkfs.xfs 相关的参数给我们使用
想要知道系统还支持哪种文件系统的格式化功能,直接按 [tab]
3.4 文件系统检验
1、xfs_repair 处理 XFS 文件系统
xfs_repair [-fnd] 设备名称
选项与参数:
-f :后面的设备其实是个文件而不是实体设备
-n :单纯检查并不修改文件系统的任何数据 (检查而已)
-d :通常用在单人维护模式下面,针对根目录 (/) 进行检查与修复的动作!很危险!不要随便使用
2、fsck.ext4 处理 EXT4 文件系统
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
3、无论是 xfs_repair 或 fsck.ext4,在正常状况下使用此一指令, 可能会造成对系统的危害
由于 xfs_repair/fsck.ext4 在扫瞄磁盘的时候,可能会造成部分 filesystem 的修订,所以“执行 xfs_repair/fsck.ext4 时, 被检查的 partition 务必不可挂载到系统上,即是需要在卸载的状态
3.5 文件系统挂载与卸载
1、挂载点是目录, 而这个目录是进入磁盘分区(其实是文件系统)的入口,进行挂载前:
- 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
- 单一目录不应该重复挂载多个文件系统;
- 要作为挂载点的目录,理论上应该都是空目录才是
如果 要用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时的消失
等到新分区被卸载之后,则原本的内容就会再次出现
mount -a
mount [-l]
mount [-t 文件系统] LABEL='' 挂载点
mount [-t 文件系统] UUID='' 挂载点
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) 的
内存机制,默认为 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: 重新挂载,这在系统出错,或重新更新参数时,很有用!
为什么能 找出文件系统类型的呢? 由于文件系统几乎都有 superblock ,Linux 可以通过分析 superblock 搭配 Linux 自己的驱动程序去测试挂载, 如果成功的套和了,就立刻自动的使用该类型的文件系统挂载起来
过去我们都习惯使用设备文件名然后直接用该文件名挂载, 不过近期以来 比较建议使用 UUID 来识别文件系统,会比设备名称与标头名称还要更可靠
范例:找出 /dev/vda4 的 UUID 后,用该 UUID 来挂载文件系统到 /data/xfs 内
blkid /dev/vda4
/dev/vda4: UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" TYPE="xfs"
mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs
mount: mount point /data/xfs does not exist # 非正规目录,所以手动创建它
mkdir -p /data/xfs
mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs
df /data/xfs
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/vda4 1038336 32864 1005472 4% /data/xfs
# 顺利挂载,且容量约为 1G 左右没问题
光驱一挂载之后 就无法退出光盘片了,除非你将他卸载才能够退出
2、挂载 vfat 中文U盘 (USB磁盘)
挂载时 指定一下挂载文件系统所使用的语系数据。 在 man mount 找到 vfat 文件格式当中可以使用 codepage 来处理,中文语系的代码为 950
如果想要指定中文是万国码还是大五码, 就得要使用 iocharset 为 utf8 还是 big5 两者择一了
范例:找出你的U盘设备的 UUID,并挂载到 /data/usb 目录中
blkid
/dev/sda1: UUID="35BC-6D6B" TYPE="vfat"
mkdir /data/usb
mount -o codepage=950,iocharset=utf8 UUID="35BC-6D6B" /data/usb
# mount -o codepage=950,iocharset=big5 UUID="35BC-6D6B" /data/usb
df /data/usb
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 2092344 4 2092340 1% /data/usb
3、重新挂载根目录与挂载不特定目录
根目录根本就不能够被卸载,如果挂载参数要改变, 或者是根目录出现“只读”状态时,如何重新挂载呢?最可能的处理方式就是重新开机(需要更改根文件系统的挂载参数,可以通过编辑 /etc/fstab 文件来实现,然后重新启动系统应用更改)
范例:将 / 重新挂载,并加入参数为 rw 与 auto
mount -o remount,rw,auto /
当 进入单人维护模式时,根目录常会被系统 挂载为只读,这个时候下面指令就太重要
也可以利用 mount 来将某个目录挂载到另外一个目录去(mount --bind)。这并不是挂载文件系统,而是额外挂载某个目录的方法
虽然下面的方法 也可以使用 symbolic link 来链接,不过 有不支持符号链接的程序
范例:将 /var 这个目录暂时挂载到 /data/var 下面:
mkdir /data/var
mount --bind /var /data/var # 从此进入 /data/var 就是进入 /var 的意思
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
# 内容完全一模一样,因为挂载目录的缘故
mount 命令列出所有当前挂载的文件系统及其详细信息,通过管道 (|) 将 mount 命令的输出传递给 grep 命令,grep var 会从中筛选出包含 "var" 字符串的行
mount | grep var # 查找当前已挂载的文件系统中包含字符串 "var" 的挂载点信息
/dev/mapper/centos-root on /data/var type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
4、umount (将设备文件卸载)
umount [-fn] 设备文件名或挂载点
选项与参数:
-f :强制卸载,可用在类似网络文件系统 (NFS) 无法读取到的情况下
-l :立刻卸载文件系统,比 -f 还强
-n :不更新 /etc/mtab 情况下卸载
cd /data/cdrom
umount /data/cdrom
umount: /data/cdrom: target is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))
目前正在 /data/cdrom/ 的目录内,也就是说其实“你正在使用该文件系统”的意思,离开该文件系统的挂载点 即可,可以使用“ cd / ”回到根目录,就能够卸载 /data/cdrom
3.6 磁盘/文件系统参数修订
1、修改一下目前文件系统的一些相关信息,举例来说,可能要修改 Label name(标签名可以用来代替设备名(例如 /dev/sda1)进行挂载操作), 或者是 journal 的参数(通常指的是 journalctl 命令,用于查看和操作系统日志),或者是其他磁盘/文件系统运行时的相关参数 (例如 DMA(允许外设直接读写系统内存) 启动与否)
2、mknod
文件如何代表该设备:通过文件的 major 与 minor 数值来替代的
ll /dev/vda*
brw-rw----. 1 root disk 252, 0 Jun 24 02:30 /dev/vda
brw-rw----. 1 root disk 252, 1 Jun 24 02:30 /dev/vda1
brw-rw----. 1 root disk 252, 2 Jun 15 23:43 /dev/vda2
brw-rw----. 1 root disk 252, 3 Jun 15 23:43 /dev/vda3
brw-rw----. 1 root disk 252, 4 Jun 24 20:00 /dev/vda4
brw-rw----. 1 root disk 252, 5 Jun 24 21:15 /dev/vda5
252 为主要设备代码,而 0~5 则为次要设备代码;Linux 核心认识的设备数据就是通过这两个数值来决定
硬件文件名已经都可以被系统自动的实时产生,某些情况下面 可能还是得要手动处理设备文件的,例如在某些服务被关到特定目录下时(chroot)
mknod 设备文件名 [bcp] [Major] [Minor]
选项与参数:
设备种类:
b :设置设备名称成为一个周边储存设备文件,例如磁盘等;
c :设置设备名称成为一个周边输入设备文件,例如鼠标/键盘等;
p :设置设备名称成为一个 FIFO 文件(用于在两个进程之间进行有序的数据通信);
Major :主要设备代码;
Minor :次要设备代码;
# 由上述的介绍我们知道 /dev/vda10 设备代码 252, 10;252 与 10 是有意义的,不要随意设置
mknod /dev/vda10 b 252 10
ll /dev/vda10
brw-r--r--. 1 root root 252, 10 Jun 24 23:40 /dev/vda10
创建一个 FIFO 文件,文件名为 /tmp/testpipe
mknod /tmp/testpipe p
ll /tmp/testpipe
prw-r--r--. 1 root root 0 Jun 24 23:44 /tmp/testpipe
# 这个文件可不是一般文件,不可以随便就放在这里!测试完毕之后请删除这个文件
rm /dev/vda10 /tmp/testpipe
rm: remove block special file '/dev/vda10' ? y
rm: remove fifo '/tmp/testpipe' ? y
3、xfs_admin 修改 XFS 文件系统的 UUID 与 Label name
当初格式化的时候 忘记加上标头名称,后来想要再次加入时,不需要重复格式化。直接使用这个 xfs_admin 即可
xfs_admin [-lu] [-L label] [-U uuid] 设备文件名
选项与参数:
-l :列出这个设备的 label name
-u :列出这个设备的 UUID
-L :设置这个设备的 label name
-U :设置这个设备的 UUID
设置 /dev/vda4 的 label name 为 vbird_xfs,并测试挂载
xfs_admin -L vbird_xfs /dev/vda4
writing all SBs
new label = "vbird_xfs" # 产生新的 LABEL 名称啰!
xfs_admin -l /dev/vda4
label = "vbird_xfs"
mount LABEL=vbird_xfs /data/xfs/
范例:利用 uuidgen 产生新 UUID 来设置 /dev/vda4,并测试挂载
umount /dev/vda4 # 使用前,请先卸载!
uuidgen
e0fa7252-b374-4a06-987a-3cb14f415488 # 很有趣的指令,可以产生新的 UUID
xfs_admin -u /dev/vda4
UUID = e0a6af55-26e7-4cb7-a515-826a8bd29e90
xfs_admin -U e0fa7252-b374-4a06-987a-3cb14f415488 /dev/vda4
Clearing log and setting UUID
writing all SBs
new UUID = e0fa7252-b374-4a06-987a-3cb14f415488
mount UUID=e0fa7252-b374-4a06-987a-3cb14f415488 /data/xfs
因为 没有办法指定这个磁盘在所有的 Linux 系统中,文件名一定都会是 /dev/vda,要用 UUID 来作为挂载时写入的设备名称 而不是 设备文件名(/dev/vda4)
在 当前测试系统当中查询到的文件名是 /dev/sda,但是当这个U盘放到其他的已经有 /dev/sda 文件名的 Linux 系统下,它的文件名就会被指定成为 /dev/sdb 或 /dev/sdc 等等
4、tune2fs 修改 ext4 的 label name 与 UUID
tune2fs [-l] [-L Label] [-U uuid] 设备文件名
选项与参数:
-l :类似 dumpe2fs -h 的功能,将 superblock 内的数据读出来
-L :修改 LABEL name
-U :修改 UUID
范例:列出 /dev/vda5 的 label name 之后,将它改成 vbird_ext4
dumpe2fs -h /dev/vda5 | grep name
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name: <none> # 果然是没有设置的
tune2fs -L vbird_ext4 /dev/vda5
dumpe2fs -h /dev/vda5 | grep name
Filesystem volume name: vbird_ext4
mount LABEL=vbird_ext4 /data/ext4
4、设置开机挂载
让系统“自动”在开机时进行挂载
4.1 开机挂载 /etc/fstab 及 /etc/mtab
1、系统挂载的一些限制:
- 根目录 / 是必须挂载的,而且一定要先于其它 mount point 被挂载进来
- 其它 mount point 必须为已创建的目录,可任意指定,但一定要遵守 必须的系统目录架构原则 (FHS)
- 所有 mount point 在同一时间之内,只能挂载一次
- 所有 partition 在同一时间之内,只能挂载一次
- 如若进行卸载,必须先将工作目录移到 mount point(及其子目录) 之外
2、/etc/fstab:
cat /etc/fstab
# Device Mount point filesystem parameters dump fsck
/dev/mapper/centos-root / xfs defaults 0 0
UUID=94ac5f77-cb8a-495e-a65b-2ef7442b837c /boot xfs defaults 0 0
/dev/mapper/centos-home /home xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
/etc/fstab (filesystem table) 就是将 mount 指令进行挂载时, 将所有的选项与参数 写入到这个文件中就是了
这个文件的内容共有六个字段
[设备/UUID等] [挂载点] [文件系统] [文件系统参数] [dump] [fsck]
1)第一栏:磁盘设备文件名/UUID/LABEL name:
这个字段可以填写的数据主要有三个项目(选一个填):
- 文件系统或磁盘的设备文件名,如 /dev/vda2 等
- 文件系统的 UUID 名称,如 UUID=xxx
- 文件系统的 LABEL 名称,例如 LABEL=xxx
记得使用 blkid 或 xfs_admin 来查询 UUID
2)第二栏:挂载点 (mount point):
一定是目录
3)第三栏:磁盘分区的文件系统:
在手动挂载时 可以让系统自动测试挂载,但在这个文件当中 必须要手动写入文件系统,包括 xfs, ext4, vfat, reiserfs, nfs 等等
4)第四栏:文件系统参数:
同步和非同步 主要涉及到 数据的读写请求如何被处理 以及 对这些请求的响应机制
如果一个文件对所有者有执行权限且设置了SUID位,那么在权限字符串中,执行位会被’S’代替,当它被执行时,将使用文件所有者的权限来运行,而不是执行者的权限
如果一个文件对所属组有执行权限且设置了SGID位,执行位会被’S’代替,当它被执行时,将使用文件所属组的权限来运行
第五栏:能否被 dump 备份指令作用:
dump 是一个用来做为备份的指令,不过现在有太多的备份方案了,直接输入 0 就好
第六栏:是否以 fsck 检验扇区:
早期开机的流程中,会有一段时间 去检验本机的文件系统,看看文件系统是否完整 (clean)。 不过这个方式使用的 主要是通过 fsck 去做的,现在用的 xfs 文件系统 就没有办法适用,因为 xfs 会自己进行检验,不需要额外进行这个动作,所以直接填 0
假设 要将 /dev/vda4 每次开机都自动挂载到 /data/xfs
nano /etc/fstab
UUID="e0fa7252-b374-4a06-987a-3cb14f415488" /data/xfs xfs defaults 0 0
最后测试一下 刚刚我们写入 /etc/fstab 的语法有没有错误
mount -a
df /data/xfs
/etc/fstab 是开机时的配置文件,不过,实际 filesystem 的挂载是记录到 /etc/mtab 与 /proc/mounts 这两个文件当中的,每次 在更动 filesystem 的挂载时,也会同时更动这两个文件
当系统因 /etc/fstab 文件中的错误配置而无法正常启动时,通常会建议进入单用户模式(有时称为“救援模式”或“维护模式”)来修正问题。在单用户模式下,系统将阻止多用户登录,并且通常以只读(read-only)模式挂载根文件系统(/)
只读模式防止了任何可能的文件系统损坏,因为没有任何文件可以被修改或删除。这对于诊断问题和修复配置时特别重要,以确保不会因为误操作而造成数据丢失
在系统启动早期阶段,许多系统服务尚未初始化,此时如果根文件系统是可读写的,可能会导致数据不一致或服务冲突
万一发生 在 /etc/fstab 输入的数据错误,导致无法顺利开机成功,而进入单人维护模式当中,那时候的 / 可是 read only 的状态,当然 就无法修改 /etc/fstab ,也无法更新 /etc/mtab,可以利用下面这一招:
使用mount命令 以可读写模式重新挂载根文件系统
mount -o remount,rw /
使用文本编辑器(如vi, nano)编辑 /etc/fstab 文件,修正错误的条目
在保存更改并退出编辑器后,可以使用 blkid 命令验证分区的UUID或标签是否正确匹配 /etc/fstab 中的条目
使用 df -h 检查文件系统是否正确挂载
使用 reboot 命令重启系统
4.2 特殊设备 loop 挂载 (镜像文件不烧录就挂载使用)
1、如果有光盘镜像文件,或者是使用文件作为磁盘的方式时,要使用特别的方法来将他挂载起来,不需要烧录
2、挂载光盘/DVD镜像文件
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
mkdir /data/centos_dvd
mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /data/centos_dvd
df /data/centos_dvd
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 4050860 4050860 0 100% /data/centos_dvd
以在这个文件内“动手脚”去修改文件
3、创建大文件以制作 loop 设备文件
制作出一个大文件,然后将这个文件格式化后挂载,能够帮助我们解决很多系统的分区不良的情况
1)创建大型文件
如果当初在分区时, 只有分区出一个根目录,假设 已经没有多余的容量可以进行额外的分区,根目录的容量还很大,此时 就能够制作出一个大文件,然后将这个文件挂载,如此一来感觉上 就多了一个分区
使用 dd 来创建空的文件,假设 要创建一个空的文件在 /srv/loopdev
dd if=/dev/zero of=/srv/loopdev bs=1M count=512
512+0 records in # 读入 512 笔数据
512+0 records out # 输出 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 就是这个文件的容量
ll -h /srv/loopdev
-rw-r--r--. 1 root root 512M Jun 25 19:46 /srv/loopdev
将 512 块,每块 1MB 的砖块堆叠成为一个大文件 (/srv/loopdev)
2)大型文件的格式化
默认 xfs 不能够格式化文件的,所以要格式化文件 得要加入特别的参数
-f 或 --force:强制创建文件系统,即使设备上已有数据。使用时要小心,因为这将清除设备上的所有数据
mkfs.xfs -f /srv/loopdev
blkid /srv/loopdev
/srv/loopdev: UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" TYPE="xfs"
3)挂载
利用 mount 的特殊参数,-o loop 的参数
mount -o loop UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" /mnt
df /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 520876 26372 494504 6% /mnt
感觉上 就可以在原本的分区在不更动原有的环境下 制作出 想要的分区
尤其是想要玩 Linux 上面的“虚拟机”的话, 也就是 以一部 Linux 主机再切割成为数个独立的主机系统时,类似 VMware 这类的软件, 在 Linux 上使用 xen 这个软件,他就可以配合这种 loop device 的文件类型 来进行根目录的挂载
将这个文件系统永远的自动挂载起来
nano /etc/fstab
/srv/loopdev /data/file xfs defaults**,loop** 0 0
使用文件名进行管理:在创建文件系统并将其挂载到循环设备时,记录下原始文件的路径和名称。在需要进行卸载、重新挂载或修改 /etc/fstab 中的条目时,直接使用这个文件名,这样可以避免因UUID解析错误或块设备变更引起的混乱
维护文件与UUID的关联:在某些情况下,记录下文件与生成的文件系统的UUID之间的对应关系可能是有益的,特别是当你需要在/etc/fstab中使用UUID来指定挂载点时。这有助于确保即使文件或设备名称发生变化,文件系统仍能被正确地识别和挂载
umount /mnt
mkdir /data/file
mount -a # 尝试重新挂载在 /etc/fstab 文件中定义的所有文件系统
df /data/file
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 520876 26372 494504 6% /data/file
5、内存交换空间(swap)的创建
以前的年代因为内存不足,因此那个可以暂时将内存的程序 拿到硬盘中暂放的内存交换空间 (swap) 就显的非常的重要
早期在安装 Linux 之前,常常会告诉你: 安装时一定需要的两个 partition ,一个是根目录,另外一个就是 swap(内存交换空间)
CPU 所读取的数据 都来自于内存, 那当内存不足的时候,为了让后续的程序可以顺利的运行,因此在内存中暂不使用的程序与数据就会被挪到 swap 中了
由于 不会知道何时会有大量来自网络的要求,因此最好还是 能够预留一些 swap 来缓冲一下系统的内存用量
创建 swap
1)设置一个 swap partition
2)创建一个虚拟内存的文件
5.1 使用实体分区创建swap
1、创建 swap 分区
分区:先使用 gdisk 在磁盘中 分区出一个分区 给系统作为 swap 。由于 Linux 的 gdisk 默认会将分区的 ID 设置为 Linux 的文件系统,所以 可能还得要设置一下 system ID
格式化:利用创建 swap 格式的“mkswap 设备文件名”就能够格式化该分区成为 swap 格式
使用:最后将该 swap 设备启动,方法为:“swapon 设备文件名”
观察:最终通过 free 与 swapon -s 这个指令来观察一下内存的用量
1)先进行分区
通常,在使用分区工具如 fdisk、gdisk 或 parted 对磁盘进行操作之后,执行 partprobe 命令 可以让系统立即更新其对磁盘分区的认识
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
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
x extra functionality (experts only)
? print this menu
gdisk /dev/vda
Command (? for help): n
Partition number (6-128, default 6):
First sector (34-83886046, default = 69220352) or {+-}size{KMGTP}:
Last sector (69220352-83886046, default = 83886046) or {+-}size{KMGTP}: +512M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8200
Changed type of partition to 'Linux swap'
Command (? for help): p
Number Start (sector) End (sector) Size Code Name
6 69220352 70268927 512.0 MiB 8200 Linux swap # 重点就是产生这东西!
Command (? for help): w
Do you want to proceed? (Y/N): y
partprobe
lsblk # 用于列出所有块设备及其属性
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 252:0 0 40G 0 disk
.....(中间省略).....
`-vda6 252:6 0 512M 0 part # 确定这里是存在的才行
2)开始创建 swap 格式
mkswap /dev/vda6
# 创建交换空间,在创建交换空间之前,确保分区或文件已经清空或未被格式化,因为 mkswap 过程会清除分区上的所有数据
Setting up swapspace version 1, size = 524284 KiB
no label, UUID=6b17e4ab-9bf9-43d6-88a0-73ab47855f9d
blkid /dev/vda6 # 用于查询和显示系统中所有块设备的 UUID、文件系统类型、标签以及其他相关属性
/dev/vda6: UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d" TYPE="swap"
块设备(block device)指的是 能够以固定大小的数据块进行读写操作的设备。这些设备通常与存储有关,它们允许 操作系统和应用程序 以块的形式访问数据,而不需要 关心数据的实际物理位置
块设备通过内核的设备驱动程序 进行管理,并且 被映射到一个文件系统路径下,例如 /dev/sda、/dev/hdc 或者 /dev/mapper/vg-lv 等。常见的块设备包括:
硬盘驱动器(HDD)
固态驱动器(SSD)
光驱(CD/DVD/Blu-ray)
USB闪存驱动器(U盘)
SD卡
虚拟磁盘(如在虚拟机中)
RAID阵列
LVM(Logical Volume Manager)逻辑卷
磁带驱动器(尽管通常被视为字符设备,但在某些情况下也可以作为块设备使用)
块设备通常具有以下特性:
它们支持随机访问,意味着 可以从任何位置读取或写入数据,而不必按顺序进行
数据 被组织成一系列固定大小的块,通常每个块的大小是512字节、4096字节(4KB)或其他大小,这取决于 具体的设备和文件系统
操作系统 可以通过块设备接口发送读写请求,由设备驱动程序负责 将这些请求转换为硬件上的实际操作
3)开始观察与载入
free
total used free shared buff/cache available
Mem: 1275140 227244 330124 7804 717772 875536 # 实体内存
Swap: 1048572 101340 947232 # swap 相关
# 有 1275140K 的实体内存,使用 227244K 剩余 330124K ,使用掉的内存有 717772K 用在缓冲/高速缓存的用途中。至于 swap 已经有 1048572K
swapon /dev/vda6
free
total used free shared buff/cache available
Mem: 1275140 227940 329256 7804 717944 874752
Swap: 1572856 101260 1471596 # 增加了
swapon -s # 目前使用的 swap 设备有哪些
Filename Type Size Used Priority
/dev/dm-1 partition 1048572 101260 -1
/dev/vda6 partition 524284 0 -2
nano /etc/fstab # 写入配置文件,只不过不是文件系统,所以没有挂载点,第二个字段写入 swap 即可
UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d" swap swap defaults 0 0
free 用于报告系统中物理内存(RAM)和交换内存(Swap)的使用情况。free 命令提供了实时的内存使用统计
5.2 使用文件创建swap
1、如果是 在实体分区无法支持的环境下,此时 前一小节提到的 loop 设备创建方法 就派的上用场,与实体分区不一样的,这个方法只是利用 dd 去创建一个大文件而已
1)使用 dd 这个指令来新增一个 128MB 的文件在 /tmp 下面:
dd if=/dev/zero of=/tmp/swap bs=1M count=128
128+0 records in
128+0 records out
134217728 Bytes (134 MB) copied, 1.7066 seconds, 78.6 MB/s
ll -h /tmp/swap
-rw-r--r--. 1 root root 128M Jun 26 17:47 /tmp/swap
2)使用 mkswap 将 /tmp/swap 这个文件格式化为 swap 的文件格式:
mkswap /tmp/swap
Setting up swapspace version 1, size = 131068 KiB
no label, UUID=4746c8ce-3f73-4f83-b883-33b12fa7337c
# 这个指令下达时请“特别小心”,因为下错字符控制,将可能使文件系统挂掉
3)使用 swapon 来将 /tmp/swap 启动
swapon /tmp/swap # 激活或附加交换空间(swap space)的命令
swapon -s # 显示所有激活的交换空间
Filename Type Size Used Priority
/dev/dm-1 partition 1048572 100380 -1
/dev/vda6 partition 524284 0 -2
/tmp/swap file 131068 0 -3
4)使用 swapoff 关掉 swap file,并设置自动启用
nano /etc/fstab
/tmp/swap swap swap defaults 0 0
# 为何这里不要使用 UUID 呢?这是因为系统仅会查询区块设备 (block device) 不会查询文件
# 所以,这里千万不要使用 UUID,不然系统会查不到
涉及到使用如 swapon 或 mount 这类命令来激活交换空间或挂载文件系统时,系统通常会查找并识别块设备
swapoff /tmp/swap /dev/vda6
[root@study ~]# swapon -s
Filename Type Size Used Priority
/dev/dm-1 partition 1048572 100380 -1
# 确定已经回复到原本的状态
swapon -a # 激活所有在 /etc/fstab 文件中指定为交换空间的设备或文件
swapon -s
# 最终你又会看正确的三个 swap 出现,这也才确定你的 /etc/fstab 设置无误
Linux 主机系统可以进入“休眠”模式的话,那么, 运行当中的程序状态 则会被纪录到 swap 去,以作为“唤醒”主机的状态依据
6、文件系统的特殊观察与操作
6.1 磁盘空间之浪费问题
整个文件系统中包括 superblock, inode table 与其他中介数据等其实都会浪费磁盘容量
在 /dev/vda4, /dev/vda5 创建起 xfs/ext4 文件系统时, 一挂载就立刻有很多容量被用掉了
当使用 ls -l 去查询某个目录下的数据时,第一行都会出现一个“total”的字样,其实那就是该目录下的所有数据 所耗用的实际 block 数量 * block 大小的值
如果计算每个文件实际容量的加总结果,其实只有不到 5K 而已
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 -> /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
6.2 利用 GNU 的 parted 进行分区行为
gdisk 主要针对 GPT 而 fdisk 主要支持 MBR ,对 GPT 的支持还不够,所以使用不同的分区时,得要先查询到正确的分区表才能用适合的指令
同时支持的指令:parted
parted [设备] [指令 [参数]]
选项与参数:
指令功能:
新增分区:mkpart [primary|logical|extended] [ext4|vfat|xfs] 开始 结束
显示分区:print
删除分区:rm [partition]
- 分区类型
Primary 分区:这是最基本的分区类型,可以直接使用而无需通过其他分区访问。通常,一个硬盘最多可以有四个主分区
Extended 分区:扩展分区本身不可直接使用,但它可以包含多个逻辑分区。扩展分区的存在是为了突破四个分区的限制,因为在扩展分区内部,可以创建多个逻辑分区
Logical 分区:逻辑分区位于扩展分区内部,可以有多个,它们是作为扩展分区的一部分被创建的,通常用于存储数据 - 文件系统类型
ext4:是 Linux 系统中最常用的文件系统之一,支持大文件和大磁盘,具有日志功能,提供高性能和数据完整性。
vfat:也称为 FAT16 或 FAT32,是一种兼容性非常好的文件系统,几乎所有的操作系统都能识别和读写 vfat 文件系统,常用于移动存储设备。
xfs:是另一种高性能的文件系统,特别适合于大文件和高I/O负载的场景,提供在线文件系统修复和良好的性能
起始点:分区的起始位置在这颗磁盘的多少 MB 处,以容量作为单位
如果 想要将原本的 MBR 改成 GPT 分区表,或原本的 GPT 分区表改成 MBR 分区表,也能使用 parted,但是请不要使用 vda 来测试,因为分区表格式不能转换
将 /dev/sda 这个原本的 MBR 分区表变成 GPT 分区表(危险,无法复原!)
parted /dev/sda print
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sda: 2148MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos # 确实显示的是 MBR 的 msdos 格式喔!
parted /dev/sda mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on
this disk will be lost. Do you want to continue?
Yes/No? y
parted /dev/sda print
# 会看到变成 gpt,后续的分区就全部都死掉了
创建一个约为 512MB 容量的分区
parted /dev/vda print
.....(前面省略).....
Number Start End Size File system Name Flags
.....(中间省略).....
6 35.4GB 36.0GB 537MB linux-swap(v1) Linux swap # 要先找出来下一个分区的起始点!
parted /dev/vda mkpart primary fat32 36.0GB 36.5GB
# 由于新的分区的起始点在前一个分区的后面,所以要先找出前面那个分区的 End 位置
# 然后再请参考 mkpart 的指令功能,就能够处理好相关的动作
parted /dev/vda print
.....(前面省略).....
Number Start End Size File system Name Flags
7 36.0GB 36.5GB 522MB primary
partprobe
lsblk /dev/vda7
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda7 252:7 0 498M 0 part # 要确定它是真的存在才行
mkfs -t vfat /dev/vda7 # -t 或 --type:用于指定要创建的文件系统的类型
blkid /dev/vda7
/dev/vda7: SEC_TYPE="msdos" UUID="6032-BF38" TYPE="vfat"
nano /etc/fstab
UUID="6032-BF38" /data/win vfat defaults 0 0
mkdir /data/win
mount -a
df /data/win
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/vda7 509672 0 509672 0% /data/win
在运行 mkfs 命令之前,请确保设备没有被挂载,并且里面没有重要数据,因为创建文件系统会清除设备上的所有数据
应该使用 gdisk 来处理 GPT 分区,某些特殊时刻,例如你要自己写脚本,让分区全部一口气创建, 不需要 gdisk 一条一条指令去进行时,那么 parted 就非常有效果了。因为他可以直接进行 partition 而不需要跟用户互动,这就是它的最大好处