初识Linux(四)------ Linux 磁盘与文件系统管理
1. Linux 文件系统
1.1 文件系统特性
我们都知道磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个文件系统。 为什么需要进行“格式化”呢?这是因为每种操作系统所设置的文件属性/权限并不相同, 为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的“文件系统格式(filesystem)”。
windows 98 主要利用的文件系统是 FAT (或 FAT16),windows 2000 以后的版本有所谓的 NTFS 文件系统,至于 Linux 的正统文件系统则为 Ext2 (Linux second extended file system, ext2fs)。在默认的情况下,windows 操作系统是不会认识 Linux 的 Ext2 的。
传统的磁盘与文件系统应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如LVM与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统(例如LVM),也能够将多个分区合成一个文件系统(LVM, RAID)! 所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区。
那么文件系统是如何运行的呢?这与操作系统的文件有关。较新的操作系统的文件除了文件实际内容外, 通常含有非常多的属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。 文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 data block 区块中。 另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。
每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:
- superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量, 以及文件系统的格式与相关信息等;
- inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
- block:实际记录文件的内容,若文件太大时,会占用多个 block 。
我们将 inode 与 block 区块用图解来说明一下,如下图所示,文件系统先格式化出 inode 与 block 的区块,假设某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为 2, 7, 13, 15 这四个 block 号码,此时我们的操作系统就能够据此来排列磁盘的读取顺序,可以一口气将四个 block 内容读出来。
这种数据存取的方法我们称为索引式文件系统(indexed allocation)。
我们常用的U盘(闪存)使用的文件系统一般为 FAT 格式。FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一下读取出来。每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像下面这样:
所谓的“碎片整理” 的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差。 这个时候可以通过碎片整理将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易。 FAT 的文件系统需要不时的碎片整理一下,那么 Ext2 是否需要呢?由于 Ext2 是索引式文件系统,基本上不太需要常常进行碎片整理的。
1.2 Linux 的 EXT2 文件系统(inode)
文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。如果我的文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不明智的,因为 inode 与 block 的数量太庞大,不容易管理。因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统。
文件系统最前面有一个开机扇区(boot sector),这个启动扇区可以安装开机管理程序, 这是个非常重要的设计,因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整块磁盘唯一的 MBR, 这样也才能够制作出多重引导的环境。
data block (数据区块)
data block 是用来放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录。
文件系统限制表
- 原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
- 每个 block 内最多只能够放置一个文件的数据;
- 如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
- 若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)。
inode table (inode 表格)
基本上,inode 记录的文件数据至少有下面这些:
- 该文件的读写属性(read/write/excute);
- 该文件的拥有者与用户组(owner/group);
- 该文件的大小;
- 该文件创建或状态改变的时间(ctime);
- 最近一次的读取时间(atime);
- 最近修改的时间(mtime);
- 定义文件特性的标识(flag),如 SetUID...;
- 该文件真正内容指向 (pointer);
inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有:
- 每个 inode 大小均固定为 128 Bytes (新的 ext4 与 xfs 可设置到 256 Bytes);
- 每个文件都仅会占用一个 inode 而已;
- 承上,因此文件系统能够创建的文件数量与 inode 的数量有关;
- 系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容。
我们来举例分析一下 EXT2 的 inode / block 与文件大小的关系。inode 要记录的数据非常多,但偏偏又只有 128Bytes , 而 inode 记录一个 block 号码要花掉 4Byte ,假设我一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万个block 号码的记录!inode 哪有这么多空间?为此系统将 inode 记录 block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。
这样子 inode 能够指定多少block大小 呢?我们以较小的 1K block 来说明好了,可以指定的情况如下:
- 12 个直接指向: 12*1K=12K
- 间接: 256*1K=256K
每个 block 号码的记录会花去 4Bytes,因此 1K 的大小能够记录 256 个记录,因此一个间接可以记录的文件大小如上;
- 双间接: 256*256*1K=2562K
- 三间接: 256*256*256*1K=2563K
总额:12 + 256 + 256*256 + 256*256*256 (K) = 16GB
此时我们知道当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为 16GB,比较一下文件系统限制表的结果可发现是一致的!但这个方法不能用在 2K 及 4K block 大小的计算中, 因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合。
Superblock (超级区块)
Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。他记录的信息主要有:
- block 与 inode 的总量;
- 未使用与已使用的 inode / block 数量;
- block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128Bytes 或 256Bytes);
- filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
- 一个 valid bit 数值,若此文件系统已被挂载,则有效位为 0 ,若未被挂载,则 valid bit 为 1 。
一般来说, superblock 的大小为 1024B。superblock信息可用 dumpe2fs 命令来查看。
此外,每个 block group 都可能含有 superblock ,但是我们也说一个文件系统应该仅有一个 superblock 而已,事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock , 而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份。
Filesystem Description (文件系统描述说明)
这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap对照表, inodemap(inode对照表), data block) 分别介于哪一个 block 之间。这部分也能够用 dumpe2fs 来查看。
block bitmap (区块对照表)
如果想要新增文件时会用到 block,选择“空的 block ”来记录新文件的数据。这就要通过 block bitmap 的辅助了。从 block bitmap 当中可以知道哪些 block 是空的,因此我们的系统就能够很快速的找到可使用的空间来处置文件。同样的,如果删除某些文件时,那么文件原本占用的 block 号码就得要释放出来,此时在 block bitmap 当中相对应到该 block 号码的标志就要修改成为“未使用中”。
inode bitmap (inode 对照表)
与 block bitmap 类似。
dumpe2fs: 查询 Ext 家族 superblock 信息的指令
不过很可惜的是, CentOS 7 现在是以 xfs 为默认文件系统, 所以目前的系统应该无法使用 dumpe2fs 去查询任何文件系统的。
1.3 与目录树的关系
由前面介绍我们知道在 Linux 系统下,每个文件(不管是一般文件还是目录文件)都会占用一个 inode , 且可依据文件内容的大小来分配多个 block 给该文件使用。同时我们知道目录的内容在记录文件名, 一般文件才是实际记录数据内容的地方。那么目录与文件在文件系统当中是如何记录数据的呢?
目录
当我们在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码; 而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据。也就是说目录所占用的 block 内容在记录如下的信息:
目录所属的 block 内的文件名与 inode 号码对应示意图
[root@study ~]# ls -li total 8 53735697 -rw-------. 1 root root 1816 May 4 17:57 anaconda-ks.cfg 53745858 -rw-r--r--. 1 root root 1864 May 4 18:01 initial-setup-ks.cfg
文件
当我们在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小的 block 数量给该文件。
目录树读取
inode 本身并不记录文件名,文件名的记录是在目录的 block 当中。 因此在文件与目录的权限说明这一节中, 我们才会提到“新增/删除/重命名文件名与目录的 w 权限有关”!那么因为文件名是记录在目录的 block 当中, 因此当我们要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据。
由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的 inode 号码,此时就能够得到根目录的 inode 内容,并依据该 inode 读取根目录的 block 内的文件名数据,再一层一层的往下读到正确的文件名。
举例来说,如果我想要读取 /etc/passwd 这个文件时,系统是如何读取的呢?
[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
该文件的读取流程为(假设读取者身份为 dmtsai 这个一般身份使用者):
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 内容的数据读出来。
filesystem 大小与磁盘读取性能:
当你的一个文件系统规划得很大的时候,例如 100GB 这么大时, 由于磁盘上面的数据总是来来去去的,整个文件系统上面的文件通常无法连续写在一起(block 号码不连续), 只能将数据填入到没有被使用的 block 当中。如果文件写入的 block 真的分的很散, 此时就会有所谓的文件数据离散的问题发生了,这会导致读取效率低下的问题。
此时可以将整个 filesystme 内的数据全部复制出来,将该 filesystem 重新格式化, 再将数据给他复制回去即可解决这个问题。
此外,如果 filesystem 真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的 block 号码中, 此时会造成磁盘的机械手臂移动幅度过大,也会造成数据读取性能的低下。而且磁头在查找整个 filesystem 时, 也会花费比较多的时间去查找!因此, partition 的规划并不是越大越好。
1.4 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) 状态
假如你的文件在写入文件系统时,因为不知名原因导致系统中断(例如突然的停电啊、 系统核心发生错误啊~等等的怪事发生时),写入的数据仅有 inode table 及 data block 而已, 最后一个同步更新元数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存放区产生不一致 (Inconsistent) 的情况了。
在早期的 Ext2 文件系统中,如果发生这个问题, 那么系统在重新开机的时候,就会借由 Superblock 当中记录的 valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查!若有需要检查时则以 e2fsck 这个程序来进行的。不过,这样的检查真的是很费时,因为要针对 metadata 区域与实际数据存放区来进行比对, 得要搜寻整个 filesystem ,这样的检查会造成主机复原时间的变长。
日志式文件系统 (Journaling filesystem)
为了避免上述提到的文件系统不一致的情况发生,如果在我们的 filesystem 当中规划出一个区块,该区块专门在记录写入或修改文件时的步骤, 那不就可以简化一致性检查的步骤了,也就是说:
1. 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。
在这样的程序当中,万一数据的记录过程当中发生了问题,那么我们的系统只要去检查日志记录区块,就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块 filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了!这就是日志式文件最基础的功能。
1.5 Linux 文件系统的运行
我们现在知道了目录树与文件系统的关系了,同时我们也知道, 所有的数据都得要载入到内存后 CPU 才能够对该数据进行处理。想一想,如果你常常编辑一个好大的文件, 在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多, 因此你会常常耗在等待磁盘的写入/读取上,真没效率!
为了解决这个效率的问题,我们的 Linux 使用的是称为非同步处理 (asynchronously) 的方式。所谓的非同步处理是这样的:
当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设置为干净(clean)的。 但如果内存中的文件数据被更改过了,此时该内存中的数据会被设置为脏的 (Dirty)。此时所有的动作都还在内存中执行,并没有写入到磁盘中! 系统会不定时的将内存中设置为“Dirty”的数据写回磁盘,以保持磁盘与内存数据的一致性。 你也可以利用 sync指令来手动写入磁盘。
我们知道内存的速度要比磁盘快的多,因此如果能够将常用的文件放置到内存当中,这不就会增加系统性能吗? 因此:
- 系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写;
- 承上,因此 Linux 的实体内存最后都会被用光!这是正常的情况!可加速系统性能;
- 你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;
- 若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
- 但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。
1.6 挂载点的意义 (mount point)
每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。 将文件系统与目录树结合的动作我们称为“挂载”。重点是:挂载点一定是目录,该目录为进入该文件系统的入口。 因此并不是任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,才能够使用该文件系统的。
同一个 filesystem 的某个 inode 只会对应到一个文件内容, 因此我们可以通过判断 inode 号码来确认不同文件名是否为相同的文件。
[root@study ~]# 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
# XFS filesystem 最顶层的目录的 inode 一般为 128
1.7 其他 Linux 支持的文件系统与 VFS
虽然 Linux 的标准文件系统是 ext2 ,且还有增加了日志功能的 ext3/ext4 ,事实上,Linux 还有支持很多文件系统格式的, 尤其是日志式文件系统,包括 SGI 的 XFS 文件系统, 可以适用更小型文件的 Reiserfs 文件系统,以及 Windows 的 FAT 文件系统等等, 都能够被 Linux 所支持。常见的支持文件系统有:
- 传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;
- 日志式文件系统: ext3 /ext4 / ReiserFS / Windows' NTFS / IBM's JFS / SGI's XFS / ZFS
- 网络文件系统: NFS / SMBFS
想要知道你的 Linux 支持的文件系统有哪些,可以察看下面这个目录:
[root@study ~]# ls -l /lib/modules/$(uname -r)/kernel/fs
系统目前已载入到内存中支持的文件系统则有:
[root@study ~]# cat /proc/filesystems
Linux VFS (Virtual Filesystem Switch)
整个 Linux 的系统都是通过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。 也就是说,整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理,我们使用者并不需要知道每个 partition 上的 filesystem 是什么,VFS 会自动的帮我们做好读取的操作。
1.8 XFS 文件系统简介
CentOS 7 开始,默认的文件系统已经由原本的 EXT4 变成了 XFS 文件系统了。
EXT 家族:支持度最广,但格式化很慢;
xfs 适合大容量磁盘与巨型文件读取性能较佳。
XFS 文件系统的配置
基本上 xfs 就是一个日志式文件系统,xfs 文件系统在数据上,主要规划为三个部分,一个数据区 (data section)、一个文件系统活动登录区 (log section)以及一个实时运行区 (realtime section)。 这三个区域的数据内容如下:
- 数据区 (data section)
基本上,数据区就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock 等数据,都放置在这个区块。 这个数据区与 ext 家族的 block group 类似,也是分为多个储存区群组 (allocation groups) 来分别放置文件系统所需要 的数据。 每个储存区群组都包含了 (1)整个文件系统的 superblock、 (2)剩余空间的管理机制、 (3)inode的分配与追踪。此外,inode与 block 都是系统需要用到时, 这才动态配置产生,所以格式化快。
另外,与 ext 家族不同的是, xfs 的 block 与 inode 有多种不同的容量可供设置,block 容量可由 512Bytes ~ 64K 调配,不过,Linux 的环境下, 由于内存控制的关系 (页面文件 pagesize 的容量),因此最高可以使用的 block 大小为 4K 而已(本书作者鸟哥尝试格式化 block 成为 16K 是没问题的,不过,Linux 核心不给挂载! 所以格式化完成后也无法使用) 至于 inode 容量可由 256Bytes 到 2M 这。不过,大概还是保留 256Bytes 的默认值就很够用了!
- 文件系统活动登录区 (log section)
在登录区这个区域主要被用来记录文件系统的变化,其实有点像是日志区!文件的变化会在这里记录下来,直到该变化完整的写入到数据区后, 该笔记录才会结束。如果文件系统因为某些缘故 (例如最常见的停电) 而损毁时,系统会拿这个登录区块来进行检验,看看系统挂掉之前, 文件系统正在运行些什么,借以快速的修复文件系统。
因为系统所有动作的时候都会在这个区块做个记录,因此这个区块的磁盘活动是相当频繁。xfs 设计有点有趣,在这个区域中, 你可以指定外部的磁盘来作为 xfs 文件系统的日志区块!例如,你可以将 SSD 磁盘作为 xfs 的登录区,这样当系统需要进行任何活动时, 就可以更快速的进行工作。
- 实时运行区 (realtime section)
当有文件要被创建时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到 data section 的 inode 与 block。 这个 extent 区块的大小得要在格式化的时候就先指定,最小值是 4K 最大可到 1G。一般非磁盘阵列的磁盘默认为 64K 容量,而具有类似磁盘阵列的 stripe 情况下,则建议 extent 设置为与 stripe 一样大较佳。这个 extent 最好不要乱动,因为可能会影响到实体磁盘的性能。
XFS 文件系统的描述数据观察
[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
2. 文件系统的操作
2.1 磁盘与目录的容量
- df
- du
df,列出文件系统的整体磁盘使用量
[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 是与内存有关的挂载
范例二:将 /etc 下面的可用的磁盘容量以易读的容量格式显示 [root@study ~]# df -h /etc Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 10G 3.3G 6.8G 33% / # 这个范例比较有趣一点啦,在 df 后面加上目录或者是文件时, df # 会自动的分析该目录或文件所在的 partition ,并将该 partition 的容量显示出来, # 所以,您就可以知道某个目录下面还有多少容量可以使用了! ^_^ 范例三:将目前各个 partition 当中可用的 inode 数量列出 [root@study ~]# df -ih Filesystem Inodes IUsed IFree IUse% Mounted on /dev/mapper/centos-root 10M 108K 9.9M 2% / devtmpfs 154K 397 153K 1% /dev tmpfs 156K 5 156K 1% /dev/shm tmpfs 156K 497 156K 1% /run tmpfs 156K 13 156K 1% /sys/fs/cgroup # 这个范例则主要列出可用的 inode 剩余量与总容量。分析一下与范例一的关系, # 你可以清楚的发现到,通常 inode 的数量剩余都比 block 还要多
需要注意的是,如果使用 -a 这个参数时,系统会出现 /proc 这个挂载点,但是里面的东西都是 0 ,不要紧张! /proc 的东西都是 Linux 系统所需要载入的系统数据,而且是挂载在“内存当中”的, 所以没有占任何的磁盘空间。
至于那个 /dev/shm/ 目录,其实是利用内存虚拟出来的磁盘空间,通常是总实体内存的一半! 由于是通过内存虚拟出来的磁盘,因此你在这个目录下面创建任何数据文件时,存取速度是非常快速的!(在内存工作) 不过,也由于他是内存虚拟出来的,因此这个文件系统的大小在每部主机上都不一样,而且创建的东西在下次开机时就消失了。
du,查看文件系统的磁盘使用量(常用在查看目录所占磁盘空间)
[root@study ~]# du [-ahskm] 文件或目录名称 选项与参数: -a :列出所有的文件与目录容量,因为默认仅统计目录下面的文件量而已。 -h :以人们较易读的容量格式 (G/M) 显示; -s :列出总量而已,而不列出每个各别的目录占用容量; -S :不包括子目录下的总计,与 -s 有点差别。 -k :以 KBytes 列出容量显示; -m :以 MBytes 列出容量显示;
范例一:列出目前目录下的所有文件大小 [root@study ~]# du 4 ./.cache/dconf <==每个目录都会列出来 4 ./.cache/abrt 8 ./.cache ....(中间省略).... 0 ./test4 4 ./.ssh <==包括隐藏文件的目录 76 . <==这个目录(.)所占用的总量 # 直接输入 du 没有加任何选项时,则 du 会分析“目前所在目录” # 的文件与目录所占用的磁盘空间。但是,实际显示时,仅会显示目录容量(不含文件), # 因此 . 目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量。 # 此外,输出的数值数据以 1K 为单位。 范例二:同范例一,但是将文件的容量也列出来 [root@study ~]# du -a 4 ./.bash_logout <==有文件的列表了 4 ./.bash_profile 4 ./.bashrc ....(中间省略).... 4 ./.ssh/known_hosts 4 ./.ssh 76 . 范例三:检查根目录下面每个目录所占用的容量 [root@study ~]# du -sm /* 0 /bin 99 /boot ....(中间省略).... du: cannot access ‘/proc/17772/task/17772/fd/4’: No such file or directory du: cannot access ‘/proc/17772/fdinfo/4’: No such file or directory 0 /proc <==不会占用硬盘空间! 1 /root 25 /run ....(中间省略).... 3126 /usr <==系统初期最大就是他了啦! 117 /var # 这是个很常被使用的功能~利用万用字符 * 来代表每个目录,如果想要检查某个目录下, # 哪个次目录占用最大的容量,可以用这个方法找出来。值得注意的是,如果刚刚安装好 Linux 时, # 那么整个系统容量最大的应该是 /usr 。而 /proc 虽然有列出容量,但是那个容量是在内存中, # 不占磁盘空间。至于 /proc 里头会列出一堆“No such file or directory” 的错误, # 别担心!因为是内存内的程序,程序执行结束就会消失,因此会有些目录找不到,是正确的。
与 df 不一样的是,du 这个指令其实会直接到文件系统内去搜寻所有的文件数据, 所以上述第三个范例指令的运行会执行一小段时间。
2.2 硬链接与符号链接: ln
在 Linux 下面的链接文件有两种,一种是类似 Windows 快捷方式功能的文件,可以让你快速的链接到目标文件(或目录); 另一种则是通过文件系统的 inode 链接来产生新文件名,而不是产生新文件!这种称为硬链接 (hard link)。 这两种玩意儿是完全不一样的东西。
Hard Link(硬连接)
在前一小节当中,我们知道几件重要的信息,包括:
- 每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;
- 想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。
也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。那么想一想, 有没有可能有多个文件名对应到同一个 inode 号码呢?有的!那就是 hard link 的由来。 所以简单的说:hard link 只是在某个目录下新增一笔文件名链接到某 inode 号码的关连记录而已。
举个例子来说,假设我系统有个 /root/crontab 他是 /etc/crontab 的实体链接,也就是说这两个文件名链接到同一个 inode , 自然这两个文件名的所有相关信息都会一模一样(除了文件名之外)。实际的情况可以如下所示:
[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
#可以发现两个文件名都链接到 34474855 这个 inode 号码
上图的意思是,你可以通过 1 或 2 的目录之 inode 指定的 block 找到两个不同的文件名,而不管使用哪个文件名均可以指到 real 那个 inode 去读取到最终数据!那这样有什么好处呢?最大的好处就是“安全”!如同上图中, 如果你将任何一个“文件名”删除,其实 inode 与 block 都还是存在的! 此时你可以通过另一个“文件名”来读取到正确的文件数据。
一般来说,使用 hard link 设置链接文件时,磁盘的空间与 inode 的数目都不会改变! 由图中可以知道, hard link 只是在某个目录下的 block 多写入一个关连数据而已,既不会增加 inode 也不会消耗用 block 数量。
hard link 限制:
- 不能跨 Filesystem;
- 不能 link 目录。(=._.=)原文解释没看懂
能 hard link 到目录又是怎么回事呢?这是因为如果使用 hard link 链接到目录时, 链接的数据需要连同被链接目录下面的所有数据都创建链接,举例来说,如果你要将 /etc 使用实体链接创建一个 /etc_hd 的目录时,那么在 /etc_hd 下面的所有文件名同时都与 /etc 下面的文件名要创建 hard link 的,而不是仅链接到 /etc_hd 与 /etc 而已。 并且,未来如果需要在 /etc_hd 下面创建新文件时,连带的, /etc 下面的数据又得要创建一次 hard link ,因此造成相当大的复杂度。
ps: 链接的是目录的inode,不需要和目录下的每个文件都建立硬连接吧,没懂。
Symbolic Link (符号链接,快捷方式)
基本上, Symbolic link 就是在创建一个独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的文件名!由于只是利用文件来做为指向的操作, 所以,当来源文件被删除之后,symbolic link 的文件会“打开不了”, 会一直说“无法打开某文件!”。实际上就是找不到原始“文件名”而已。
[root@study ~]# ln -s /etc/crontab crontab2 [root@study ~]# 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了!
由 1 号 inode 读取到链接文件的内容仅有文件名,根据文件名链接到正确的目录去取得目标文件的 inode , 最终就能够读取到正确的数据了。你可以发现的是,如果目标文件(/etc/crontab)被删除了,那么整个环节就会无法继续进行下去, 所以就会发生无法通过链接文件读取的问题了。
这里还是得特别留意,这个 Symbolic Link 与 Windows 的快捷方式可以划上等号,由 Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉 inode 与 block。
由上面的说明来看,似乎 hard link 比较安全,因为即使某一个目录下的关连数据被删除了, 也没有关系,只要有任何一个目录下存在着关连数据,那么该文件就不会不见。不过由于 Hard Link 的限制太多了,包括无法做“目录”的 link , 所以在用途上面是比较受限的,反而是 Symbolic Link 的使用方面较广。
[root@study ~]# ln [-sf] 来源文件 目标文件 选项与参数: -s :如果不加任何参数就进行链接,那就是hard link,至于 -s 就是symbolic link -f :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建!
使用 ln 如果不加任何参数的话,那么就是 Hard Link。
关于目录的 link 数量:
当我们以 hard link 进行“文件的链接”时,可以发现,在 ls -l 所显示的第二字段会加一,那么,如果创建目录时,他默认的 link 数量会是多少? 让我们来想一想,一个“空目录”里面至少会存在些什么?那就是存在 . 与 .. 这两个目录。那么,当我们创建一个新目录名称为 /tmp/testing 时,基本上会有三个东西,那就是:
- /tmp/testing
- /tmp/testing/.
- /tmp/testing/..
而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的!都代表该目录啊~而 /tmp/testing/.. 则代表 /tmp 这个目录,所以说,当我们创建一个新的目录时, “新的目录的 link 数为 2 ,而上层目录的 link 数则会增加 1 ”
[root@study ~]# ls -ld /tmp drwxrwxrwt. 14 root root 4096 Jun 23 22:42 /tmp
[root@study ~]# mkdir /tmp/testing1
[root@study ~]# ls -ld /tmp drwxrwxrwt. 15 root root 4096 Jun 23 22:45 /tmp # 这里的 link 数量加 1 了!
[root@study ~]# ls -ld /tmp/testing1 drwxr-xr-x. 2 root root 6 Jun 23 22:45 /tmp/testing1/
3. 磁盘的分区、格式化、检验与挂载
如果我们想要在系统里面新增一颗磁盘时,应该有哪些需要做的呢:
- 对磁盘进行分区,以创建可用的 partition ;
- 对该 partition 进行格式化 (format),以创建系统可用的 filesystem;
- 若想要仔细一点,则可对刚刚创建好的 filesystem 进行检验;
- 在 Linux 系统上,需要创建挂载点 (亦即是目录),并将他挂载上来;
当然,在上述的过程当中,还有很多需要考虑的,例如磁盘分区 (partition) 需要定多大? 是否需要加入 journal 的功能?inode 与 block 的数量应该如何规划等等的问题。但是这些问题的决定, 都需要与你的主机用途来加以考虑。
3.1 观察磁盘分区状态
由于目前磁盘分区主要有 MBR 以及 GPT 两种格式,这两种格式所使用的分区工具不太一样!当然也可以使用最后才介绍的 parted 这个都有支持的工具来处理,不过,我们还是比较习惯使用 fdisk 或者是 gdisk 来处理分区啊。因此,我们自然就得要去找一下目前系统有的磁盘有哪些? 这些磁盘是 MBR 还是 GPT 等等的!这样才能处理。
lsblk 列出系统上的所有磁盘列表,list block device
[root@study ~]# lsblk [-dfimpt] [device] 选项与参数: -d :仅列出磁盘本身,并不会列出该磁盘的分区数据 -f :同时列出该磁盘内的文件系统名称 -i :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用) -m :同时输出该设备在 /dev 下面的权限数据 (rwx 的数据) -p :列出该设备的完整文件名!而不是仅列出最后的名字而已。 -t :列出该磁盘设备的详细数据,包括磁盘伫列机制、预读写的数据量大小等
范例一:列出本系统下的所有磁盘与磁盘内的分区信息 [root@study ~]# 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:挂载点
blkid 列出设备的 UUID 等参数
虽然 lsblk 已经可以使用 -f 来列出文件系统与设备的 UUID 数据,不过,比较习惯直接使用 blkid 来找出设备的 UUID。UUID 是全局唯一标识符(universally unique identifier),Linux 会将系统内所有的设备都给予一个独一无二的标识符, 这个标识符就可以拿来作为挂载或者是使用这个设备/文件系统。
[root@study ~]# blkid /dev/vda2: UUID="94ac5f77-cb8a-495e-a65b-2ef7442b837c" TYPE="xfs" /dev/vda3: UUID="WStYq1-P93d-oShM-JNe3-KeDl-bBf6-RSmfae" TYPE="LVM2_member" /dev/sda1: UUID="35BC-6D6B" TYPE="vfat" /dev/mapper/centos-root: UUID="299bdc5b-de6d-486a-a0d2-375402aaab27" TYPE="xfs" /dev/mapper/centos-swap: UUID="905dc471-6c10-4108-b376-a802edbd862d" TYPE="swap" /dev/mapper/centos-home: UUID="29979bf1-4a28-48e0-be4a-66329bf727d9" TYPE="xfs"
如上所示,每一行代表一个文件系统,主要列出设备名称、UUID 名称以及文件系统的类型 (TYPE)。
parted 列出磁盘的分区表类型与分区信息
虽然我们已经知道了系统上面的所有设备,并且通过 blkid 也知道了所有的文件系统!不过,还是不清楚磁盘的分区类型。 这时我们可以通过 parted 来输出。
[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
3.2 磁盘分区: gdisk/fdisk
MBR 分区表请使用 fdisk 分区, GPT 分区表请使用 gdisk 分区。
3.2.1 gdisk
[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): <==这里可以让你输入指令动作,可以按问号 (?) 来查看可用指令 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):
查看分区表信息:
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
- 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 ” 就会发生错误,要使用 gdisk /dev/vda 才对!
ps:还有一些操作略过了,感觉用不上。
3.2.2 fdisk
fdisk 跟 gdisk 使用的方式几乎一样。
[root@study ~]# fdisk /dev/sda Command (m for help): m <== 输入 m 后,就会看到下面这些指令介绍 Command action a toggle a bootable flag b edit bsd disklabel c toggle the dos compatibility flag d delete a partition <==删除一个partition l list known partition types m print this menu n add a new partition <==新增一个partition o create a new empty DOS partition table p print the partition table <==在屏幕上显示分区表 q quit without saving changes <==不储存离开fdisk程序 s create a new empty Sun disklabel t change a partition's system id u change display/entry units v verify the partition table w write table to disk and exit <==将刚刚的动作写入分区表 x extra functionality (experts only)
3.3 磁盘格式化(创建文件系统)
分区完毕后自然就是要进行文件系统的格式化,格式化的指令非常的简单,那就是“make filesystem, mkfs” 这个指令。这个指令其实是个综合的指令,他会去调用正确的文件系统格式化工具软件,因为 CentOS 7 使用 xfs 作为默认文件系统, 下面我们会先介绍 mkfs.xfs ,之后介绍新一代的 EXT 家族成员 mkfs.ext4,最后再聊一聊 mkfs 这个综合指令。
3.3.1 XFS 文件系统 mkfs.xfs
我们常听到的“格式化”其实应该称为“创建文件系统 (make filesystem)”才对。因此使用的是 mkfs.xfs 这个指令
[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|1]:log 设备是否为内置?默认为 1 内置,如果要用外部设备,使用下面设置 logdev=device :log 设备为后面接的那个设备上头的意思,需设置 internal=0 才可! size=数值 :指定这块登录区的容量,通常最小得要有 512 个 block,大约 2M 以上才行! -L :后面接这个文件系统的标头名称 Label name 的意思! -r :指定 realtime section 的相关设置值,常见的有: extsize=数值 :就是那个重要的 extent 数值,一般不须设置,但有 RAID 时, 最好设置与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。
XFS 文件系统 for RAID 性能优化
磁盘阵列是多颗磁盘组成一颗大磁盘的意思, 利用同步写入到这些磁盘的技术,不但可以加快读写速度,还可以让某一颗磁盘坏掉时,整个文件系统还是可以持续运行的状态!那就是所谓的容错。
基本上,磁盘阵列 (RAID) 就是通过将文件先细分为数个小型的分区区块 (stripe) 之后,然后将众多的 stripes 分别放到磁盘阵列里面的所有磁盘, 所以一个文件是被同时写入到多个磁盘去,当然性能会好一些。为了文件的安全性,所以在这些磁盘里面,会保留数个 (与磁盘阵列的规划有关) 备份磁盘 (parity disk), 以及可能会保留一个以上的备用磁盘 (spare disk),这些区块基本上会占用掉磁盘阵列的总容量,不过对于数据的安全会比较有保障。
3.3.2 EXT4 文件系统 mkfs.ext4
略
3.3.3 其他文件系统 mkfs
如果想要知道系统还支持哪种文件系统的格式化功能,直接按 [tabl]
[root@study ~]# mkfs[tab][tab]
mkfs mkfs.btrfs mkfs.cramfs mkfs.ext2 mkfs.ext3 mkfs.ext4
mkfs.fat mkfs.minix mkfs.msdos mkfs.vfat mkfs.xfs
3.4 文件系统检验
由于系统在运行时说不准什么时候硬件或者是电源会有问题,所以“死机”可能是难免的情况(不管是硬件还是软件)。 现在我们知道文件系统运行时会有磁盘与内存数据非同步的状况发生,因此莫名其妙的死机非常可能导致文件系统的错误。 如果文件系统真的发生错误的话,那该如何恢复!不同的文件系统恢复的指令不太一样,我们主要针对 xfs 及 ext4 这两个主流来说明。
xfs_repair 处理 XFS 文件系统
[root@study ~]# xfs_repair [-fnd] 设备名称 选项与参数: -f :后面的设备其实是个文件而不是实体设备 -n :单纯检查并不修改文件系统的任何数据 (检查而已) -d :通常用在单人维护模式下面,针对根目录 (/) 进行检查与修复的动作!很危险!不要随便使用
xfs_repair 可以检查/修复文件系统,不过,因为修复文件系统是个很庞大的任务!因此,修复时该文件系统不能被挂载,已挂载的可以先卸载。
Linux 系统有个设备无法被卸载,那就是根目录啊!如果你的根目录有问题怎办?这时得要进入单人维护或恢复模式,然后通过 -d 这个选项来处理! 加入 -d 这个选项后,系统会强制检验该设备,检验完毕后就会自动重新开机。
fsck.ext4 处理 EXT4 文件系统
#常用命令 [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
注意:通常只有身为 root 且你的文件系统有问题的时候才使用这个指令,否则在正常状况下使用此一指令, 可能会造成对系统的危害!通常使用这个指令的场合都是在系统出现极大的问题,导致你在 Linux 开机的时候得进入单机模式下进行维护的行为时,才必须使用此一指令。
另外,如果你怀疑刚刚格式化成功的磁盘有问题后,也可以使用 xfs_repair/fsck.ext4 来检查一磁盘。其实就有点像是 Windows 的 scandisk,此外,由于 xfs_repair/fsck.ext4 在扫描磁盘的时候,可能会造成部分 filesystem 的修改,所以“执行 xfs_repair/fsck.ext4 时, 被检查的 partition 务必不可挂载到系统上,需要是卸载的状态。
3.5 文件系统挂载与卸载
一开始时我们就提过挂载点是目录, 而这个目录是进入磁盘分区(其实是文件系统)的入口。不过要进行挂载前,最好先确定几件事:
- 单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
- 单一目录不应该重复挂载多个文件系统;
- 要作为挂载点的目录,理论上应该都是空目录。
尤其是上述的后两点,如果你要用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时的消失。 举个例子来说,假设你的 /home 原本与根目录 (/) 在同一个文件系统中,下面原本就有 /home/test 与 /home/vbird 两个目录。然后你想要加入新的磁盘,并且直接挂载 /home 下面,那么当你挂载上新的分区时,则 /home 目录显示的是新分区内的数据,至于原先的 test 与 vbird 这两个目录就会暂时的被隐藏掉了!注意,并不是被覆盖掉, 而是暂时的隐藏了起来,等到新分区被卸载之后,则 /home 原本的内容就会再次的出现。
将文件系统挂载到我们的 Linux 系统上,就要使用 mount 这个命令,这个命令很复杂,这里只简单介绍一下。
[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 的数据将所有未挂载的磁盘都挂载上来 -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: 重新挂载,这在系统出错,或重新更新参数时,很有用!
基本上,CentOS 7 已经很聪明了,因此基本不需要加上 -t 这个选项,系统会自动的分析最恰当的文件系统来尝试挂载你需要的设备! 这也是使用 blkid 就能够显示正确的文件系统的缘故!那 CentOS 是怎么找出文件系统类型的呢? 由于文件系统几乎都有 superblock ,Linux 可以通过分析 superblock 搭配 Linux 自己的驱动程序去测试挂载, 如果测试成功,就立刻自动的使用该类型的文件系统挂载起来。上述的挂载测试主要是参考下面这两个文件:
- /etc/filesystems:系统指定的测试挂载文件系统类型的优先顺序;
- /proc/filesystems:Linux系统已经载入的文件系统类型
那怎么知道我的 Linux 有没有相关文件系统类型的驱动程序呢?我们 Linux 支持的文件系统之驱动程序都写在如下的目录中:
- /lib/modules/$(uname -r)/kernel/fs/
3.5.1 挂载 xfs/ext4/vfat 等文件系统
范例:找出 /dev/vda4 的 UUID 后,用该 UUID 来挂载文件系统到 /data/xfs 内 [root@study ~]# blkid /dev/vda4 /dev/vda4: UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" TYPE="xfs" [root@study ~]# mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs mount: mount point /data/xfs does not exist # 非正规目录!所以手动创建它! [root@study ~]# mkdir -p /data/xfs [root@study ~]# mount UUID="e0a6af55-26e7-4cb7-a515-826a8bd29e90" /data/xfs [root@study ~]# df /data/xfs Filesystem 1K-blocks Used Available Use% Mounted on /dev/vda4 1038336 32864 1005472 4% /data/xfs # 顺利挂载,且容量约为 1G 左右没问题! 范例:使用相同的方式,将 /dev/vda5 挂载于 /data/ext4 [root@study ~]# blkid /dev/vda5 /dev/vda5: UUID="899b755b-1da4-4d1d-9b1c-f762adb798e1" TYPE="ext4" [root@study ~]# mkdir /data/ext4 [root@study ~]# mount UUID="899b755b-1da4-4d1d-9b1c-f762adb798e1" /data/ext4 [root@study ~]# df /data/ext4 Filesystem 1K-blocks Used Available Use% Mounted on /dev/vda5 999320 2564 927944 1% /data/ext4
3.5.2 挂载 CD 或 DVD 光盘
范例:将你用来安装 Linux 的 CentOS 原版光盘拿出来挂载到 /data/cdrom! [root@study ~]# blkid .....(前面省略)..... /dev/sr0: UUID="2015-04-01-00-21-36-00" LABEL="CentOS 7 x86_64" TYPE="iso9660" PTTYPE="dos" [root@study ~]# mkdir /data/cdrom [root@study ~]# mount /dev/sr0 /data/cdrom mount: /dev/sr0 is write-protected, mounting read-only [root@study ~]# df /data/cdrom Filesystem 1K-blocks Used Available Use% Mounted on /dev/sr0 7413478 7413478 0 100% /data/cdrom # 怎么会使用掉 100% 呢?是啊!因为是 DVD,所以无法再写入了。
光驱一挂载之后就无法退出光盘了!除非你将他卸载才能够退出!此外,如果你使用的是图形界面,那么系统会自动的帮你挂载这个光盘到 /media/ 里面去,也可以不卸载就直接退出,但是命令行界面没有这个福利了! ^_^
3.5.3 挂载 vfat 中文U盘 (USB磁盘)
注意,你的这个U盘不能够是 NTFS 的文件系统。
范例:找出你的U盘设备的 UUID,并挂载到 /data/usb 目录中 [root@study ~]# blkid /dev/sda1: UUID="35BC-6D6B" TYPE="vfat" [root@study ~]# mkdir /data/usb [root@study ~]# mount -o codepage=950,iocharset=utf8 UUID="35BC-6D6B" /data/usb [root@study ~]# # mount -o codepage=950,iocharset=big5 UUID="35BC-6D6B" /data/usb [root@study ~]# df /data/usb Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 2092344 4 2092340 1% /data/usb
如果带有中文文件名的数据,那么可以在挂载时指定一下挂载文件系统所使用的语系数据。 在 man mount 找到 vfat 文件格式当中可以使用 codepage 来处理,中文语系的代码为 950 。另外,如果想要指定中文是 Unicode 还是 Big5, 就得要使用 iocharset 为 utf8 还是 big5 两者择一了。
万一你使用的 USB 磁盘被格式化为 NTFS 时,那可能就得要安装 NTFS 文件系统的驱动程序,因为默认的 CentOS 7 并没有支持 NTFS 文件系统格式。
3.5.4 重新挂载根目录与挂载不特定目录
整个目录树最重要的地方就是根目录了,所以根目录根本就不能够被卸载的!问题是,如果你的挂载参数要改变, 或者是根目录出现“只读”状态时,如何重新挂载呢?最可能的处理方式就是重新开机 (reboot)! 不过你也可以这样做:
范例:将 / 重新挂载,并加入参数为 rw 与 auto
[root@study ~]# mount -o remount,rw,auto /
重点是那个“ -o remount,xx ”的选项与参数!请注意,要重新挂载 (remount) 时, 这是个非常重要的机制!尤其是当你进入单人维护模式时,你的根目录常会被系统挂载为只读。
另外,我们也可以利用 mount 来将某个目录挂载到另外一个目录去喔!这并不是挂载文件系统,而是额外挂载某个目录的方法! 虽然下面的方法也可以使用 symbolic link 来链接,不过在某些不支持符号链接的程序运行中,还是得要通过这样的方法才行。
范例:将 /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 | grep var /dev/mapper/centos-root on /data/var type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
看起来,其实两者链接到同一个 inode ^_^ 没错!通过这个 mount --bind 的功能, 可以将某个目录挂载到其他目录去,而并不是整块 filesystem 。所以从此进入 /data/var 就是进入 /var 的意思。
3.5.5 umount (将设备文件卸载)
[root@study ~]# umount [-fn] 设备文件名或挂载点 #一定要用挂载点!因为设备可能有被其他方式挂载 选项与参数: -f :强制卸载!可用在类似网络文件系统 (NFS) 无法读取到的情况下; -l :立刻卸载文件系统,比 -f 还强! -n :不更新 /etc/mtab 情况下卸载。
[root@study 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/ 的目录内,是无法卸载设备的,需要先退出该挂载点。
3.6 磁盘/文件系统参数修改
某些时刻,你可能会希望修改一下目前文件系统的一些相关信息,举例来说,你可能要修改 Label name , 或者是 journal 的参数,或者是其他磁盘/文件系统运行时的相关参数 (例如 DMA 启动与否~)。 这个时候,就得需要下面这些相关的命令功能:
mknod,修改设备代码
[root@study ~]# mknod 设备文件名 [bcp] [Major] [Minor] 选项与参数: 设备种类: b :设置设备名称成为一个周边储存设备文件,例如磁盘等; c :设置设备名称成为一个周边输入设备文件,例如鼠标/键盘等; p :设置设备名称成为一个 FIFO 文件; Major :主要设备代码; Minor :次要设备代码;
[root@study ~]# 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 为主要设备代码 (Major) 而 0~5 则为次要设备代码 (Minor)。 我们的 Linux 核心认识的设备数据就是通过这两个数值来决定的!举例来说,常见的磁盘文件名 /dev/sda 与 /dev/loop0 设备代码如下所示:
Linux 核心 2.6 版以后,硬件文件名已经都可以被系统自动的实时产生了,我们根本不需要手动创建设备文件。
xfs_admin 修改 XFS 文件系统的 UUID 与 Label name
如果你当初格式化的时候忘记加上标头名称,后来想要再次加入时,不需要重复格式化!直接使用这个 xfs_admin 即可。 这个指令直接拿来处理 LABEL name 以及 UUID。
[root@study ~]# xfs_admin [-lu] [-L label] [-U uuid] 设备文件名 选项与参数: -l :列出这个设备的 label name -u :列出这个设备的 UUID -L :设置这个设备的 Label name -U :设置这个设备的 UUID 喔! 范例:设置 /dev/vda4 的 label name 为 vbird_xfs,并测试挂载 [root@study ~]# xfs_admin -L vbird_xfs /dev/vda4 writing all SBs new label = "vbird_xfs" # 产生新的 LABEL 名称啰! [root@study ~]# xfs_admin -l /dev/vda4 label = "vbird_xfs" [root@study ~]# mount LABEL=vbird_xfs /data/xfs/
tune2fs 修改 ext4 的 label name 与 UUID
[root@study ~]# tune2fs [-l] [-L Label] [-U uuid] 设备文件名 选项与参数: -l :类似 dumpe2fs -h 的功能~将 superblock 内的数据读出来~ -L :修改 LABEL name -U :修改 UUID 啰! 范例:列出 /dev/vda5 的 label name 之后,将它改成 vbird_ext4 [root@study ~]# dumpe2fs -h /dev/vda5 | grep name dumpe2fs 1.42.9 (28-Dec-2013) Filesystem volume name: <none> # 果然是没有设置的! [root@study ~]# tune2fs -L vbird_ext4 /dev/vda5 [root@study ~]# dumpe2fs -h /dev/vda5 | grep name Filesystem volume name: vbird_ext4 [root@study ~]# mount LABEL=vbird_ext4 /data/ext4
4. 设置启动挂载
手动处理 mount 不是很人性化,我们需要让系统“自动”在开机时自动进行挂载。
系统挂载的一些限制:
- 根目录 / 是必须挂载的﹐而且一定要先于其它 mount point 被挂载进来。
- 其它 mount point 必须为已创建的目录﹐可任意指定﹐但一定要遵守必须的系统目录架构原则 (FHS)
- 所有 mount point 在同一时间之内﹐只能挂载一次。
- 所有 partition 在同一时间之内﹐只能挂载一次。
- 如若进行卸载﹐必须先将工作目录移到 mount point(及其子目录) 之外。
4.1 开机挂载 /etc/fstab 及 /etc/mtab
查阅一下 /etc/fstab 这个文件的内容
[root@study ~]# 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 指令进行挂载时, 会将所有的选项与参数写入到这个文件中。除此之外, /etc/fstab 还加入了 dump 这个备份用指令的支持,与开机时是否进行文件系统检验 fsck 等指令有关。 这个文件的内容共有六个字段,各个字段的总结数据与详细数据如下:
- Device,磁盘设备文件名/UUID/LABEL name;
- Mount point
- filesystem
- parameters,文件系统参数
- dump,能否被 dump 备份命令作用
dump 是一个用来做为备份的指令,不过现在有太多的备份方案了,所以这个项目可以不要理会,直接输入 0 就好了。
- fsck,是否以 fsck 检验扇区
早期开机的流程中,会有一段时间去检验本机的文件系统,看看文件系统是否完整 (clean)。 不过这个方式使用的主要是通过 fsck 去做的,我们现在用的 xfs 文件系统就没有办法适用,因为 xfs 会自己进行检验,不需要额外进行这个动作!所以直接填 0 就好了。
/etc/fstab 是开机时的配置文件,不过,实际 filesystem 的挂载是记录到 /etc/mtab 与 /proc/mounts 这两个文件当中的。每次我们在更动 filesystem 的挂载时,也会同时更动这两个文件。但是,万一你在 /etc/fstab 输入的时候发生数据错误,导致无法顺利开机成功,而进入单人维护模式当中,那时候的 / 可是 read only 的状态,当然你就无法修改 /etc/fstab ,也无法更新 /etc/mtab。可以:
[root@study ~]# mount -n -o remount,rw /
4.2 特殊设备 loop 挂载
如果有光盘镜像文件,或者是使用文件作为磁盘的方式时,那就得要使用特别的方法来将他挂载起来,不需要烧录。
略
5. 内存交换空间(swap)之创建
以前因为内存不足,因此会暂时将内存的程序拿到硬盘中的内存交换空间 (swap)暂放。一般来说,如果硬件的配备资源足够的话,那么 swap 应该不会被我们的系统所使用到。
5.1 使用物理分区创建swap
1. 分区:先使用 gdisk 在你的磁盘中分区出一个分区给系统作为 swap 。由于 Linux 的 gdisk 默认会将分区的 ID 设置为 Linux 的文件系统,所以你可能还得要设置一下 system ID 就是了。
[root@study ~]# 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 [root@study ~]# partprobe [root@study ~]# 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 设备文件名”就能够格式化该分区成为 swap 格式
3. 使用:最后将该 swap 设备启动,方法为:“swapon 设备文件名”。
[root@study ~]# mkswap /dev/vda6 Setting up swapspace version 1, size = 524284 KiB no label, UUID=6b17e4ab-9bf9-43d6-88a0-73ab47855f9d [root@study ~]# blkid /dev/vda6 /dev/vda6: UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d" TYPE="swap"
4. 观察:最终通过 free 与 swapon -s 这个指令来观察一下内存的用量吧!
[root@study ~]# 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 啰!这样会看了吧?! [root@study ~]# swapon /dev/vda6 [root@study ~]# free total used free shared buff/cache available Mem: 1275140 227940 329256 7804 717944 874752 Swap: 1572856 101260 1471596 <==有看到增加了没? [root@study ~]# swapon -s Filename Type Size Used Priority /dev/dm-1 partition 1048572 101260 -1 /dev/vda6 partition 524284 0 -2 # 上面列出目前使用的 swap 设备有哪些的意思! [root@study ~]# nano /etc/fstab UUID="6b17e4ab-9bf9-43d6-88a0-73ab47855f9d" swap swap defaults 0 0 # 当然要写入配置文件,只不过不是文件系统,所以没有挂载点!第二个字段写入 swap 即可
5.2 使用文件创建swap
如果是在硬件分区无法支持的环境下,此时前一小节提到的 loop 设备创建方法就派的上用场,与实体分区不一样的,这个方法只是利用 dd 去创建一个大文件。
1. 使用 dd 这个指令来新增一个 128MB 的文件
[root@study ~]# 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 [root@study ~]# ll -h /tmp/swap -rw-r--r--. 1 root root 128M Jun 26 17:47 /tmp/swap
2. 使用 mkswap 将 /tmp/swap 这个文件格式化为 swap 的文件格式:
[root@study ~]# mkswap /tmp/swap Setting up swapspace version 1, size = 131068 KiB no label, UUID=4746c8ce-3f73-4f83-b883-33b12fa7337c
3. 使用 swapon 来将 /tmp/swap 启动
[root@study ~]# swapon /tmp/swap [root@study ~]# 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,并设置自动启用
[root@study ~]# nano /etc/fstab /tmp/swap swap swap defaults 0 0 # 为何这里不要使用 UUID 呢?这是因为系统仅会查询区块设备 (block device) 不会查询文件! # 所以,这里千万不要使用 UUID,不然系统会查不到喔! [root@study ~]# swapoff /tmp/swap /dev/vda6 [root@study ~]# swapon -s Filename Type Size Used Priority /dev/dm-1 partition 1048572 100380 -1 # 确定已经回复到原本的状态了!然后准备来测试!! [root@study ~]# swapon -a [root@study ~]# swapon -s # 最终你又会看正确的三个 swap 出现!这也才确定你的 /etc/fstab 设置无误
说实话,swap 在目前的PC来讲,存在的意义已经不大了。这是因为目前的 x86 主机所含的内存实在都很太大了 (至少也都有 4GB ),所以,我们的 Linux 系统大概都用不到 swap 这个玩意儿的。不过, 如果是针对服务器或者是工作站这些常年上线的系统来说的话,那么,无论如何,swap 还是需要创建的。
因为 swap 主要的功能是当实体内存不够时,则某些在内存当中所占的程序会暂时被移动到 swap 当中,让实体内存可以被需要的程序来使用。另外,如果你的主机支持电源管理模式, 也就是说,你的 Linux 主机系统可以进入“休眠”模式的话,那么, 运行当中的程序状态则会被记录到 swap 去,以作为“唤醒”主机的状态依据! 另外,有某些程序在运行时,本来就会利用 swap 的特性来存放一些数据段, 所以, swap 来是需要创建的,只是不需要太大。
6. 文件系统的特殊观察与操作
6.1 磁盘空间之浪费问题
我们在前面的 EXT2 data block 介绍中谈到了一个 block 只能放置一个文件, 因此太多小文件将会浪费非常多的磁盘容量。但你有没有注意到,整个文件系统中包括 superblock, inode table 与其他中介数据等其实都会浪费磁盘容量。所以当我们在 /dev/vda4, /dev/vda5 创建起 xfs/ext4 文件系统时, 一挂载就立刻有很多容量被用掉了。
另外,不知道你有没有发现到,当你使用 ls -l 去查询某个目录下的数据时,第一行都会出现一个“total”的字样, 其实那就是该目录下的所有数据所耗用的实际 block 数量 × block 大小的值。 我们可以通过 ll -s 来观察看看上述的意义:
[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 -> /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
举例来说,那个 crontab 虽然仅有 451Bytes , 不过他却占用了整个 block (每个 block 为 4K),所以将所有的文件的所有的 block 加总就得到 12KBytes 那个数值了。 如果计算每个文件实际容量的加总结果,其实只有不到 5K 而已~所以,这样就耗费掉好多容量了!未来在讨论小磁盘、 大磁盘,文件大小的损耗时,要回想到这个区块。
6.2 利用 GNU 的 parted 进行分区行为
虽然可以使用 gdisk/fdisk 很快速的分区,不过 gdisk 主要针对 GPT 而 fdisk 主要支持 MBR ,对 GPT 的支持还不够。所以使用不同的分区时,得要先查询到正确的分区表才能用适合的指令,好麻烦!有没有同时支持的指令呢?有的!那就是 parted。
parted 可以直接在一行命令行就完成分区,是一个非常好用的指令!它常用的语法如下:
[root@study ~]# parted [设备] [指令 [参数]] 选项与参数: 指令功能: 新增分区:mkpart [primary|logical|extended] [ext4|vfat|xfs] 开始 结束 显示分区:print 删除分区:rm [partition] 范例一:以 parted 列出目前本机的分区表数据 [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 <==是 GPT 还是 MBR 分区 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 4 33.3GB 34.4GB 1074MB xfs Linux filesystem 5 34.4GB 35.4GB 1074MB ext4 Microsoft basic data 6 35.4GB 36.0GB 537MB linux-swap(v1) Linux swap [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ]
1. Number:这个就是分区的号码,举例来说,1号代表的是 /dev/vda1 的意思;
2. Start:分区的起始位置在这颗磁盘的多少 MB 处?以容量作为单位
3. End:此分区的结束位置在这颗磁盘的多少 MB 处?
4. Size:由上述两者的分析,得到这个分区有多少容量;
5. File system:分析可能的文件系统类型为何的意思!
6. Name:就如同 gdisk 的 System ID 之意。
突然有一天假期结束,时来运转,人生才是真正开始了。