第 5 章 Linux 磁盘管理
第 5 章 Linux 磁盘管理
一般情况下,采购回来的磁盘都是裸磁盘,需要格式化成文件系统后才能存储数据,所以磁盘管理和文件系统管理是密不可分的。当今主流的硬盘有机械硬盘和固态硬盘两种形态。下面分别介绍。
5.1、机械硬盘
机械硬盘由多块盘片组成,它们都绕着主轴旋转。
每块盘片上下方都有读写磁头悬浮在盘片上下方,它们与盘片的距离极小。
每次读写数据时盘片旋转,读写磁头被磁臂控制着不断的移动来读取其中的数据。
所有的盘片都是同时同步转动,所有的磁头也是同步移动。
磁盘在物理上划分了扇区、磁道和柱面。如果划分了分区,则分区是逻辑上柱面的分隔边界。
读写磁头在停止状态下,在盘片旋转时磁头扫过的一圈轨迹称为磁道,所有的磁道都是同心圆。从盘片外圈开始向内数,磁道号从 0 开始逐数增加。
每个磁道以 512 字节等分为多个弧段,每个弧段就是一个扇区。但是需要说明的是,扇区的大小并非一定是 512 字节。
所以外圈磁道的扇区数较多,内圈磁道的扇区数较少,有些硬盘参数上写的磁道扇区数通常用一个范围来标识,如 373-768 表示最外圈磁道有 768 个扇区,最内圈有 373 个扇区,这就可以计算出每个磁道的字节数。
扇区上记录了物理数据、扇区号、磁头号(或者盘片号)及磁道号。
旧式磁盘的结构不分区(without zones),每个磁道扇区数相同,但是每个扇区仍然是 512 字节,也就是说磁性材料记录的 0 和 1 的数量是相同的。这种结构的缺点是外圈磁道的面积大,存储的数据分布宽松,内圈磁道面积小,存储的数据分布密集,这样就导致盘片外圈面积浪费。
新式磁盘结构进行了分区,将每个磁道等面积划分 512 字节的空间作为一个扇区,所以不同磁道扇区数不同。
现在的磁盘都是新式扇区划分结构。
将所有盘片相同磁道数的磁道划分为柱面。和磁道号的标记方式一样,从外向内从 0 开始逐数增加。
之所以划分柱面,是因为所有磁盘同步旋转,所有磁头同步移动,所有的磁头在任意一个时刻总是会出在同一个磁道同一个扇区上。读写数据时,任意一段数据总是按柱面来读写的。所以盘片数越多,读写所扫的扇区数就越少,所需的时间相对就越少,性能就越好。
向磁盘写数据是从外圈柱面向内圈柱面写的,只有写完一个柱面才写下一个柱面。
5.2、固态硬盘
不像机械硬盘里的一摞子圆形碟片,SSD 是由一些电路和黑色的存储颗粒构成。
SSD 硬盘是基于 NAND Flash 存储技术的,属于非易失性存储设备,换成人话说,就是掉电了数据不会丢。
其中每一个黑色的存储颗粒也叫做一个 Die。 我们 "拆开" 一个 Die 来看一下。
每个 Die 有若干个 Plane,每个 Plane 有若干个 Block,每个 Block 有若干个 Page。Page 是磁盘进行读写的最小单位,一般为 2KB/4KB/8KB/16KB 等。
5.2.1、SSD 扇区
由于历史原因,操作系统等软件里,512KB 扇区的概念是“根深蒂固”。新的机械硬盘虽然把物理扇区已经做到 4KB 的了,但为了兼容老系统还得整出个逻辑扇区的概念来适配。
到了 SSD 里也一样,虽然每一个物理 Page 的大小为 2K 到 16K 不等,但是为了兼容性,也必须得整出个逻辑扇区才行。
SSD 控制器在逻辑上会把整个磁盘再重新划分成一个个的“扇区”,采用和新机械硬盘一样的 LBA 方式来进行编址(整个磁盘的扇区从 0 到某个最大值方式排列,并连成一条线)。
当需要读取某几个 "扇区" 上数据的时候,SSD 控制器通过访问这个 LBA MapTable, 再来找到要实际访问的物理 Page,如下图:
- 假设某 SSD 的 Page 大小是 4KB,一个文件是 16KB。那么该文件是存在一个黑色的存储颗粒里,还是多个?
- 假设只写在一个颗粒里,那么对该文件进行读取的时候,就只能用到一条 Flash 通道,这样速度就会比较慢。
- 如果存在相邻的 4 个颗粒里,每个写入 4KB。这样多个 Flash 通道的带宽会充分发挥出来,传输速度也更快。所以,实际中是分散在多个。
5.2.2、闪存单元
SSD 是由一个个的 Page 组成。而在每一个 Page 里,又包含了许许多多的闪存单元。。现代的闪存单元有多种类型,目前主流的主要分为 SLC、MLC 和 TLC。
在 SLC 里,一个单元的电压只分成高低两种状态,所以只能表示 1bit 数据。
到了 MLC,硬是把一个单元里的电压按照高低分成了四种状态,所以可以表示 2bit。
到了TLC,直接一个单元应拆分成8个电压高低不同的状态,为了表示3bit。
- 由于TLC在数据读写需要八种不同电压状态,而施加不同的电压状态、 就需要更精确,也就需要更长的时间才能得以实现。另外由于电压状态多,出错的可能性也会更大。
以上三种闪存单元对比:从性能和稳定性角度来看,SLC 最好。从容量角度看,TLC 最大。这就是为什么日常我们看到的工业级的 SSD 要比笔记本 SSD 要贵很多,其中一个很重要的原因就是工业级的盘往往采用的闪存单元是 SLC 或 MLC,而我们家用的笔记本一般都是 TCL,因为便宜嘛。目前主流闪存类型 TLC 居多,因为价格便宜,容量大。
闪存类型 | 单 cell 电压变化 | 单 cell 表示 bit 数 | 速度 | 擦写次数 | 价格 |
---|---|---|---|---|---|
SLC(Single-Level Cell) | 两种 | 1 bit | 快 | 约 10W 次 | 贵 |
MLC(Multi-Level Cell) | 四种 | 2 bit | 一般 | 约 3K 次 | 一般 |
TLC(Trinary-Level Cell) | 八种 | 3 bit | 慢 | 约 1K 次 | 便宜 |
5.3、分区
分区是为了在逻辑上将某些柱面隔开形成边界。它是以柱面为单位来划分的,但是从 CentOS 7 开始,是按照扇区进行划分的。
在磁盘数据量非常大的情况下,划分分区的好处是扫描块位图等更快速:不用再扫描整块磁盘的块位图,只需扫描对应分区的块位图。
5.3.1、分区方法
MBR 格式的磁盘中,会维护磁盘第一个扇区——MBR 扇区,在该扇区中第 446 字节之后的 64 字节是分区表,每个分区占用 16 字节,所以限制了一块磁盘最多只能有 4 个主分区(Primary, P),如果多于 4 个区,只能创建主分区少于 4 个,通过建立扩展分区(Extend, E),然后在扩展分区建立逻辑分区(Logical, L)的方式来突破 4 个分区的限制,逻辑分区的数量不限制。
在 Linux 中,MBR 格式的磁盘主分区号从 1 - 4,扩展分区号从 2 - 4,逻辑分区号从 5 开始。
例如,一块盘想分成6个分区,方式如下
- 1P+5L:sda1 + sda5 + sda6 + sda7 + sda8 + sda9
- 2P+4L:sda1 + sda2 + sda5 + sda6 + sda7 + sda8
- 3P+3L:sda1 + sda2 + sda3 + sda5 + sda6 + sda7
而 GPT 格式突破了 MBR 的限制,它不再限制只能存储 4 个分区表条目,而是使用了类似 MBR 扩展分区表条目的格式,它允许有 128 个主分区,这也使得它可以对超过 2TB 的磁盘进行分区。
5.3.2、MBR 和 GPT 分区表
在 MBR 格式分区表中,MBR 扇区占用 512 个字节,前 446 个字节是主引导记录,即 boot loader。
中间 64 字节记录着分区表信息,每个主分区信息占用 16 字节,因此最多只能有 4 个主分区,最后 2 个字节是有效标识位。
如果使用扩展分区,则扩展分区对应的 16 字节记录的是指向扩展分区中扩展分区表的指针。
在 MBR 磁盘上,分区和启动信息是保存在一起的,如果这部分数据被覆盖或破坏,只能重建 MBR。
而 GPT 在整个磁盘上保存多个这部分信息的副本,因此它更为健壮,并可以恢复被破坏的这部分信息。
GPT 还为这些信息保存了循环冗余校验码(CRC)以保证其完整和正确,如果数据被破坏,GPT 会发现这些破坏,并从磁盘上的其他地方进行恢复。
下面是 GPT 格式的分区表信息,大致约占 17 个字节。
EFI 部分可以分为 4 个区域:EFI 信息区(GPT头)、分区表、GPT 分区区域和备份区域。
- EFI 信息区(GPT头):起始于磁盘的 LBA1,通常也只占用这个单一扇区。其作用是定义分区表的位置和大小。GPT 头还包含头和分区表的校验和,这样就可以及时发现错误。
- 分区表:分区表区域包含分区表项。这个区域由 GPT 头定义,一般占用磁盘 LBA2~LBA33 扇区,每扇区可存储 4 个主分区的分区信息,所以共能分 128 个主分区。分区表中的每个分区项由起始地址、结束地址、类型值、名字、属性标志、GUID 值组成。分区表建立后,128 位的 GUID 对系统来说是唯一的。
- GPT 分区:最大的区域,由分配给分区的扇区组成。这个区域的起始和结束地址由 GPT 头定义。
- 备份区:备份区域位于磁盘的尾部,包含 GPT 头和分区表的备份。它占用 GPT 结束扇区和 EFI 结束扇区之间的 33 个扇区。其中最后一个扇区用来备份 1 号扇区的 EFI 信息,其余的 32 个扇区用来备份 LBA2~LBA33 扇区的分区表。
5.3.3、添加磁盘
正常情况下,添加磁盘后需要重启系统才能被内核识别,在 /dev/ 下才有对应的设备号,使用 fdisk -l 才会显示出来。但是有时候不方便重启,所以下面介绍一种磁盘热插拔方式。
# 查看主机scsi总线号
[root@compute1 ~]# ls /sys/class/scsi_host/
host0 host1 host2 host3 host4
[root@compute1 ~]#
重新扫描 scsi 总线以热插拔方式添加新设备。
[root@compute1 ~]# echo "- - -" > /sys/class/scsi_host/host0/scan
[root@compute1 ~]# echo "- - -" > /sys/class/scsi_host/host1/scan
[root@compute1 ~]# echo "- - -" > /sys/class/scsi_host/host3/scan
[root@compute1 ~]# echo "- - -" > /sys/class/scsi_host/host4/scan
# 再查看就有了
[root@compute1 ~]# fdisk -l
5.3.4、交互式命令
交互式命令的好处在于,可以每一步完成一个小目标,最后实现整体目标,思路更加清晰,排错更加容易等。
5.3.4.1、fdisk 命令
fdisk 工具用来分 MBR 磁盘上的区。要分 GPT 磁盘上的区,可以使用 gdisk。parted 工具对这两种格式的磁盘分区都支持。
如果一个存储设备已经分过区,那么它可能是 mbr 格式的,也可能是 gpt 格式的,如果已经是 mbr 格式的,则只能继续使用 fdisk 进行分区,如果已经是 gpt 格式的,则只能使用 gdisk 进行分区。
当然,无论什么格式的都可以使用 parted 进行分区,只不过也只能划分和已存在分区格式一样的分区,因为无论何种格式的分区,它的分区表和分区标识是已经固定的。
使用 fdisk 分区,它只能实现 MBR 格式的分区。
root@arm64v8:~# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
命令(输入 m 获取帮助): m
Help:
DOS (MBR)
a toggle a bootable flag
b edit nested BSD disklabel
c toggle the dos compatibility flag
Generic
d delete a partition # 删除分区,如果删除扩展分区同时会删除里面的逻辑分区
F list free unpartitioned space # 列出空闲未分区的空间
l list known partition types # 列出分区类型
n add a new partition # 创建新的分区
p print the partition table # 查看分区表
t change a partition type # 修改分区类型
v verify the partition table # 查看剩下多少未分配的扇区
i print information about a partition # 查看分区详情
Misc
m print this menu
u change display/entry units
x extra functionality (experts only)
Script
I load disk layout from sfdisk script file
O dump disk layout to sfdisk script file
Save & Exit
w write table to disk and exit
q quit without saving changes
Create a new label
g create a new empty GPT partition table
G create a new empty SGI (IRIX) partition table
o create a new empty DOS partition table
s create a new empty Sun partition table
命令(输入 m 获取帮助):
新建第一个主分区
root@arm64v8:~# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
命令(输入 m 获取帮助): n # 新建分区
Partition type
p primary (0 primary, 0 extended, 4 free) # 添加主分区
e extended (container for logical partitions) # 添加扩展分区
Select (default p): p # 选择建立主分区
分区号 (1-4, default 1): 1 # 输入分区号,从1开始
First sector (2048-209715199, default 2048): 2048 # 输入起始扇区
Last sector, +sectors or +size{K,M,G,T,P} (2048-209715199, default 209715199): +10G # 分区给10G大小
Created a new partition 1 of type 'Linux' and of size 10 GiB.
命令(输入 m 获取帮助): p # 查看分区建立的情况
Disk /dev/vdb: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2528187f
设备 启动 Start 末尾 扇区 Size Id 类型
/dev/vdb1 2048 20973567 20971520 10G 83 Linux
命令(输入 m 获取帮助):
新建扩展分区
命令(输入 m 获取帮助): n # 新建分区
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): e # 建立扩展分区
分区号 (2-4, default 2): # 选择分区号,默认就可以
First sector (20973568-209715199, default 20973568): # 起始扇区
Last sector, +sectors or +size{K,M,G,T,P} (20973568-209715199, default 209715199): # 结束扇区,这里默认把剩下的所有空间都用上
Created a new partition 2 of type 'Extended' and of size 90 GiB.
命令(输入 m 获取帮助): p # 查看扩展分区有没有成功
Disk /dev/vdb: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2528187f
设备 启动 Start 末尾 扇区 Size Id 类型
/dev/vdb1 2048 20973567 20971520 10G 83 Linux
/dev/vdb2 20973568 209715199 188741632 90G 5 扩展 # 显示出来了,成功
命令(输入 m 获取帮助): n # 在扩展分区上建立逻辑分区
All space for primary partitions is in use. # 扩展分区把剩余空间用完了,即使4个主分区没用完,也没得选
Adding logical partition 5
First sector (20975616-209715199, default 20975616): # 逻辑分区起始扇区
Last sector, +sectors or +size{K,M,G,T,P} (20975616-209715199, default 209715199): # 逻辑分区结束扇区,这里默认选择最后一个扇区用完空间
Created a new partition 5 of type 'Linux' and of size 90 GiB.
命令(输入 m 获取帮助): p # 查看逻辑分区创建成功没有
Disk /dev/vdb: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2528187f
设备 启动 Start 末尾 扇区 Size Id 类型
/dev/vdb1 2048 20973567 20971520 10G 83 Linux
/dev/vdb2 20973568 209715199 188741632 90G 5 扩展
/dev/vdb5 20975616 209715199 188739584 90G 83 Linux # 逻辑分区创建成功,所有的扩展空间用完
命令(输入 m 获取帮助): w # 分区结束,保存。如果不保存,则按q,如果没保存,所有分区都白做了
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
root@arm64v8:~#
分区的过程,实质上是划分扇区以及修改分区表。
上面的 fdisk 操作全部是在内存中执行的,必须保存生效。保存后,内核还未识别该分区,可以查看 /proc/partition 目录下存在的文件,这些文件是能被内核识别的分区。
运行 partprobe 或 partx 命令重新读取分区表让内核识别新的分区,内核识别后才可以格式化。而且分区结束时按 w 保存分区表有时候会失败,提示重启,这时候运行 partprobe 命令可以代替重启就生效。
# 这个命令可以读取所有的磁盘分区,也可以用 partprobe /dev/vdb 只读一个磁盘
root@arm64v8:~# partprobe
5.3.4.2、gdisk 命令
gdisk 用来划分 gpt 分区,需要单独安装这个工具包。
root@arm64v8:~# aptitude install gdisk
下列“新”软件包将被安装。
gdisk
0 个软件包被升级,新安装 1 个, 0 个将被删除, 同时 486 个将不升级。
需要获取 189 kB 的存档。 解包后将要使用 772 kB。
读取: 1 http://archive.kylinos.cn/kylin/KYLIN-ALL 10.0/main arm64 gdisk arm64 1.0.1-1kord1 [189 kB]
已下载 189 kB,耗时 0秒 (530 kB/s)
正在选中未选择的软件包 gdisk。
(正在读取数据库 ... 系统当前共安装有 230153 个文件和目录。)
正准备解包 .../gdisk_1.0.1-1kord1_arm64.deb ...
正在解包 gdisk (1.0.1-1kord1) ...
正在处理用于 man-db (2.7.5-1kord) 的触发器 ...
正在设置 gdisk (1.0.1-1kord1) ...
root@arm64v8:~#
分区的时候直接带上设备即可。以下是对新硬盘划分 gpt 分区的过程。
root@arm64v8:~# gdisk /dev/vdb
GPT fdisk (gdisk) version 1.0.1
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
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) # 创建一个新的空的guid分区表
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 # 将分区信息写入到磁盘
x extra functionality (experts only)
? print this menu
Command (? for help):
添加一个新分区
root@arm64v8:~# gdisk /dev/vdb
GPT fdisk (gdisk) version 1.0.1
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help): n # 新建一个分区
Partition number (1-128, default 1): # 第一个分区
First sector (34-209715166, default = 2048) or {+-}size{KMGTP}: # 起始扇区选择,默认即可
Last sector (2048-209715166, default = 209715166) or {+-}size{KMGTP}: +10G # 结束扇区选择,使用+10G这种格式,它自己会计算需要多少个扇区
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): # 选择分区类型,默认即可
Changed type of partition to 'Linux filesystem'
Command (? for help): p # 查看创建分区的情况
Disk /dev/vdb: 209715200 sectors, 100.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 76D04934-547A-4030-93CE-AC4F71B6713A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 209715166
Partitions will be aligned on 2048-sector boundaries
Total free space is 188743613 sectors (90.0 GiB)
Number Start (sector) End (sector) Size Code Name
1 2048 20973567 10.0 GiB 8300 Linux filesystem
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/vdb.
The operation has completed successfully.
root@arm64v8:~#
执行 partprobe 重新读取分区表信息。
root@arm64v8:~# partprobe /dev/vdb
5.3.4.3、parted 命令
parted 支持 mbr 格式和 gpt 格式的磁盘分区。它的强大在于可以一步到位而不需要不断的交互式输入(也可以交互式)。
parted 分区工具是实时的,所以每一步操作都是直接写入磁盘而不是写进内存,它不像 fdisk/gdisk 还需要 w 命令将内存中的结果保存到磁盘中。
root@arm64v8:~# parted /dev/vdb
GNU Parted 3.2
使用 /dev/vdb
欢迎使用 GNU Parted! 输入 'help'可获得命令列表.
(parted) help
align-check TYPE N check partition N for TYPE(min|opt) alignment
help [COMMAND] print general help, or help on COMMAND
mklabel,mktable LABEL-TYPE create a new disklabel (partition table)
mkpart 分区类型 [文件系统类型] 起始点 终止点 创建一个分区
name NUMBER NAME 将编号为NUMBER 的分区命名为“NAME”
print [devices|free|list,all|NUMBER] display the partition table, available devices, free space, all found partitions, or a particular partition
quit 退出程序
rescue START END 挽救临近“起始点”、“终止点”的遗失的分区
resizepart NUMBER END resize partition NUMBER
rm NUMBER 删除编号为 NUMBER 的分区
select DEVICE choose the device to edit
disk_set FLAG STATE change the FLAG on selected device # 设置 flag
disk_toggle [FLAG] toggle the state of FLAG on selected device # 设置 flag on 或者 off
set NUMBER FLAG STATE change the FLAG on partition NUMBER
toggle [NUMBER [FLAG]] toggle the state of FLAG on partition NUMBER
unit UNIT set the default unit to UNIT
version display the version number and copyright information of GNU Parted
(parted)
常用的命令是 mklabel/rm/print/mkpart/help/quit
parted 分区的前提是磁盘已经有分区表(partition table)或磁盘标签(disk label),否则将显示 "unrecognised disk label",这是和 fdisk/gdisk 不同的地方,所以需要先使用 mklabel 创建标签或分区表。
最常见的标签(分区表)为 "msdos" 和 "gpt",其中 msdos 分区就是 MBR 格式的分区表,也就是会有主分区、扩展分区和逻辑分区的概念和限制。
使用 parted 对/dev/sda 创建 msdos 的新分区。
[root@arm64v8 ~]# parted /dev/sda
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mkpart # 创建分区
Partition type? primary/extended? primary # 选择主分区或是扩展分区
File system type? [ext2]? xfs # 这里有一定误导,这个文件系统选择是给GUID表做参考,并不会把分区格式化成 xfs
Start? 1 # 起始位置选择,注意这个 1 表示的是 1MB,默认单位就是 MB;默认单位可以用 unit <UNIT> 指定,强调 MB 和 MiB 是有区别的,1KB=10^3=1000B,1KiB=2^10=1024B,1MiB=2^20=1048576=1024KiB
End? 1024 # 结束位置,不包括 1024MB,实际上是 1MB 到 1023MB
(parted) p # 查看分区创建成功
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
(parted) mkpart primary ext4 1024 2048 # 上面的创建方式是交互式创建,可以用一行命令完成
(parted) p # 查看第二个分区创建完成
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
2 1024MB 2048MB 1023MB primary
(parted) rm 2 # 删除分区的语法,这里删除第 2 个分区
(parted) p # 查看第 2 个分区删除完成
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
(parted) mkpart extended xfs 1030 -1 # 创建扩展分区是不用指定文件系统的,会报错
Error: Invalid number.
(parted) mkpart extended 1030 -1 # 创建扩展分区的正确方式,-1 表示用完所有的剩余空间
(parted) p # 查看扩展分区创建成功
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
2 1030MB 1100GB 1098GB extended lba
(parted) mkpart # 在扩展分区上创建逻辑分区
Partition type? primary/logical? l # 可以选择主分区或者逻辑分区
File system type? [ext2]? xfs # 这里有一定误导,这个文件系统选择是给GUID表做参考,并不会把分区格式化成 xfs
Start? 1 # 起始位置选择,随意写个 1,结合下面的警告(你已经分过1MB-1024MB的分区,扩展分区的起始是1030MB,建议从这里开始),往下看
End? 1024 # 结束位置选择,随意写个 1024,结合下面的警告(你已经分过1MB-1024MB的分区,扩展分区的起始是1030MB,建议从这里开始),往下看
Warning: You requested a partition from 1000kB to 1024MB (sectors 1953..2000000).
The closest location we can manage is 1030MB to 1030MB (sectors 2011137..2011137).
Is this still acceptable to you?
Yes/No? yes # 接受建议
Warning: The resulting partition is not properly aligned for best performance. # 警告:扇区没有对齐,看上面警告括号中的sector,这是我故意没有对齐的,1024MB 和 1030MB 中间明显有一点空间,这些扇区浪费了,所以警告,最好的方式是连续划分。
Ignore/Cancel? Ignore # 选择忽略扇区没有对齐问题
(parted) p # 查看创建了一个 1030MB 到 1030MB 的分区,也就是 1 个扇区,512 Bytes。
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
2 1030MB 1100GB 1098GB extended lba
5 1030MB 1030MB 512B logical
(parted) mkpart l xfs 1030 -1 # 重新创建逻辑分区,从 1030MB 开始到 -1 结束表示用完所有的剩余空间
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? Ignore # 忽略扇区没有对齐问题
(parted) p # 查看逻辑分区成功
Model: QEMU QEMU HARDDISK (scsi)
Disk /dev/sda: 1100GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 1024MB 1023MB primary
2 1030MB 1100GB 1098GB extended lba
5 1030MB 1030MB 512B logical
6 1030MB 1100GB 1098GB logical
(parted) quit # 退出 parted 工具
- 掌握好 parted 分区工具,Linux 下的分区基本上没有什么障碍,所以上面的实验每一步我都做了详细的说明。
- parted 最难理解的就是扇区对齐问题,所以磁盘基础知识要扎实,开篇也做了详细的陈述,可以前后对照学习。
- 上面的实验是 msdos 格式的分区,gpt 格式的分区步骤更简单,只要准确地理解了上述实验中的每一步骤,gpt 格式分区也就不在话下。
5.3.5、非交互式命令
使用非交互分区时,最重要的是待分的区的起始点不能是已使用的。
可以使用 lsblk 或 fdisk -l 或 parted DEV print 来判断将要从哪个地方开始分区。
其实 parted 在非交互分区时是最佳的工具,不仅是因为其书写方式简洁,而且待分区的起点如不合理它会自动提示是否要自动调整。
5.3.5.1、fdisk 命令
fdisk 实现非交互的原理是从标准输入中读取,每读取一行传递一次操作。
所以可以有两种方式:
使用 echo 和管道传递
# 下面的命令创建了两个分区,使用默认值时传递空行即可
[root@arm64v8 ~]# echo -e "n\np\n1\n\n+5G\nn\np\n2\n\n+1G\nw\n" | fdisk /dev/sda
将操作写入到文件中,从文件中读取
# 如果要传递的操作很多,则可以将它们写入到一个文件中,从文件中读取
[root@arm64v8 ~]# echo -e "n\np\n1\n\n+5G\nn\np\n2\n\n+1G\nw\n" >/tmp/a.txt
[root@arm64v8 ~]# fdisk /dev/sda </tmp/a.txt
5.3.5.2、gdisk 命令
同理 fdisk 命令
5.3.5.3、parted 命令
parted 命令只能一次非交互一个命令中的所有动作
parted /dev/sdb mklabel msdos # 设置硬盘flag
parted /dev/sdb mkpart primary ext4 1 1000 # Mbr格式分区,分别是partition type/fstype/start/end
parted /dev/sdb mkpart 1 ext4 1M 10240M # gpt格式分区,分别是name/fstype/start/end
parted /dev/sdb mkpart 1 10G 15G # 省略fstype的交互式分区
parted /dev/sdb rm 1 # 删除分区
parted /dev/sdb p # 输出信息
如果不确定分区的起点大小,可以加上 -s 选项使用 script 模式,该模式下 parted 将回答一切默认值,如 yes、no。
[root@arm64v8 ~]# parted -s /dev/sda mkpart 3 14G 16G
Warning: You requested a partition from 14.0GB to 16.0GB.
The closest location we can manage is 15.0GB to 16.0GB.
Is this still acceptable to you?
Information: You may need to update /etc/fstab.
5.4、格式化分区
分区结束后就需要格式化创建文件系统了,格式化分区的过程就是创建文件系统的过程。
可以使用 mkfs(make filesystem) 工具进行格式化,也可以使用该工具家族的其他工具如 mkfs.ext4/mkfs.xfs 等专门针对文件系统的工具。
要查看支持的文件系统类型,只需简单的输入 mkfs 然后按两下 tab 键,就可以列出各文件系统对应的格式化命令,这些就是支持的文件系统类型。
[root@arm64v8 ~]# mkfs
mkfs mkfs.cramfs mkfs.ext3 mkfs.fat mkfs.msdos mkfs.xfs
mkfs.btrfs mkfs.ext2 mkfs.ext4 mkfs.minix mkfs.vfat
[root@arm64v8 ~]# mkfs
5.4.1、mkfs 命令
该工具非常简单,它只需指定一个可选的 "-t" 选项指定要创建的文件系统类型,如果省略则默认创建 ext2 文件系统。
该工具指定的 "-t" 选项其实是在调用对应文件系统专属的格式化工具。
mkfs [-t fstype] 分区
mkfs.<fstype> 分区
[root@arm64v8 ~]# mkfs.ext4 /dev/sda1
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
61056 inodes, 243968 blocks
12198 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=251658240
8 block groups
32768 blocks per group, 32768 fragments per group
7632 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
[root@arm64v8 ~]#
5.4.2、mke2fs 命令
mkfs.ext2/mkfs.ext3/mkfs.ext4 或 mkfs -t extX 其实都是在调用 mke2fs 命令
该工具创建文件系统时,会从 /etc/mke2fs.conf 配置中读取默认的配置项
mke2fs [ -c ] [ -b block-size ] [ -f fragment-size ] [ -g blocks-per-group ] [ -G number-of-groups ]
[ -i bytes-per-inode ] [ -I inode-size ] [ -j ] [ -N number-of-inodes ] [ -m reserved-blocks-percentage ]
[ -q ] [ -r fs-revision-level ] [ -v ] [ -L volume-label ] [ -S ] [ -t fs-type ] device [ blocks-count ]
选项说明:
-t fs-type :指定要创建的文件系统类型(ext2,ext3 ext4),若不指定,则从/etc/mke2fs.conf中获取默认的文件系统类型。
-b block-size :指定每个block的大小,有效值有1024、2048和4096,单位是字节。
-I inode-size :指定inode大小,单位为字节。必须为2的幂次方,且大于等于128字节。值越大,说明inode的集合体inode table占用越多的空
间,这不仅会挤占文件系统中的可用空间,还会降低性能,因为要扫描inode table需要消耗更多时间,但是在linux kernel 2.6.10
之后,由于使用inode存储了很多扩展的额外属性,所以128字节已经不够用了,因此ext4默认的inode size已经变为256,尽管
inode大小增大了,但因为使用inode存储扩展属性带来的性能提升远高于inode size变大导致的负面影响,所以仍建议使用256字
节的inode。
-i bytes-per-inode :指定每多少个字节就为其分配一个inode号。值越大,说明一个文件系统中分配的inode号越少,更适用于存储大量大文件,值越
小,inode号越多,更适用于存储大量小文件。该值不能小于一个block的大小,因为这样会造成inode多余。
注意,创建文件系统后该值就不能再改变了。
-c :创建文件系统前先检查设备是否有bad blocks。
-f fragment-size :指定fragments的大小,单位字节。
-g blocks-per-group :指定每个块组中的block数量。不建议修改此项。
-G number-of-groups :该选项用于ext4文件系统(严格地说是启用了flex_bg特性),指定虚拟块组(即一个extent)中包含的块组个数,必须为2的幂次方。
对于ext4文件系统来说,使用extent的功能能极大提升其性能。
-j :创建带有日志功能的文件系统,即ext3。如果要指定关于日志方面的设置,在-j的基础上再使用-J指定,不过一般默认即可,具体可
指定的选项看man文档。
-L new-volume-label :指定卷标名称,名称不得超出16字节。
-m reserved-blocks-percentage :指定文件系统保留block数量的比例,保留一部分block,可以降低物理碎片。默认比例为5%。
-N number-of-inodes :强制指定该文件系统应该分配多少个inode号,它会覆盖通过计算得出inode数量的结果(根据block大小、数量和每多少字节分配
一个inode得出Inode数量),但是不建议这么做。
-q :安静模式,可用于脚本中
-S :重建superblock和group descriptions。在所有的superblock和备份的superblock都损坏时有用。它会重新初始化superblock和
group descriptions,但不会改变inode table、bmap和imap(若真的改变,该分区数据就全丢了,还不如重新格式化)。在重建
superblock后,应该执行e2fsck来保证文件系统的一致性。但要注意,应该完全正确地指定block的大小,其改选项并不能完全保
证数据不丢失。
-v :输出详细执行过程
所以,有可能用到的选项也就 "-t" 指定文件系统类型,"-b" 指定 block 大小,"-I" 指定 inode 大小,"-i" 指定分配 inode 的比例。
[root@arm64v8 ~]# mke2fs -t ext4 -I 256 /dev/sda1 -b 4096
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
61056 inodes, 243968 blocks
12198 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=251658240
8 block groups
32768 blocks per group, 32768 fragments per group
7632 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
[root@arm64v8 ~]#
5.4.3、tune2fs 命令
该工具其实没什么太大作用,文件系统创建好后很多属性是固定不能修改的,能修改的属性很有限,且都是无关紧要的。
但有些时候还是可以用到它做些事情,例如刚创建完ext文件系统后会提示修改自检时间。
tune2fs [ -c max-mount-counts ] [ -i interval-between-checks ] [ -j ] device
-j:将ext2文件系统升级为ext3;
-c:修改文件系统最多挂载多少次后进行自检,设置为0或-1将永不自检;
-i:修改过了多少时间进行自检。时间单位可以指定为天(默认)/月/星期[d|m|w],设置为0将永不自检。
5.5、查看文件系统
5.5.1、lsblk 命令
lsblk(list block devices) 用于列出设备及其状态,主要列出非空的存储设备。其实它只会列出 /sys/dev/block 中的主次设备号文件,且默认只列出非空设备。
[root@arm64v8 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 755.8M 0 rom
sda 8:0 0 1T 0 disk
└─sda1 8:1 0 953M 0 part
vda 253:0 0 500G 0 disk
├─vda4 253:4 0 482.9G 0 part /
├─vda2 253:2 0 1G 0 part /boot
├─vda3 253:3 0 16G 0 part [SWAP]
└─vda1 253:1 0 200M 0 part /boot/efi
[root@arm64v8 ~]#
- NAME:设备名称;
- MAJ:MIN:主设备号和此设备号;
- RM:是否为可卸载设备,1 表示可卸载设备。可卸载设备如光盘、USB 等。并非能够 umount 的就是可卸载的;
- SIZE:设备总空间大小;
- RO:是否为只读;
- TYPE:是磁盘 disk,还是分区 part,亦或是 rom,还有 loop 设备;
- mountpoint:挂载点。
[root@arm64v8 ~]# lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 1T 0 disk
└─sda1 8:1 0 953M 0 part
[root@arm64v8 ~]# lsblk /dev/sda1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda1 8:1 0 953M 0 part
[root@arm64v8 ~]#
另外常用的一个选项是 "-f",它可以查看到文件系统类型,和文件系统的 uuid 和挂载点。
[root@arm64v8 ~]# lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sr0 iso9660 CentOS 7 aarch64 2018-05-08-14-09-45-00
sda
└─sda1 ext4 f2151d94-6fb5-48af-af4f-b36c403d4247
vda
├─vda4 xfs c50aefdd-bc0f-4761-a47f-60deadbc0f30 /
├─vda2 xfs cfcb5471-b488-41ab-8622-35b57ebb0395 /boot
├─vda3 swap e0421809-f014-4ea5-8183-fd96c8423be3 [SWAP]
└─vda1 vfat AD9C-FE26 /boot/efi
[root@arm64v8 ~]#
每个已经格式化的文件系统都有其类型和 uuid,而没有格式化的设备,将只显示一个Name结果,表示该设备还未进行格式化。
5.5.2、blkid 命令
虽然它有不少比较强大的功能,但一般只用它一个功能,就是查看器文件系统类型和 uuid。
[root@arm64v8 ~]# blkid
/dev/vda1: SEC_TYPE="msdos" UUID="AD9C-FE26" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="6f5cb7a5-6d83-4f67-af13-1f01f31eb637"
/dev/vda2: UUID="cfcb5471-b488-41ab-8622-35b57ebb0395" TYPE="xfs" PARTUUID="efc59722-5d36-4bcd-87a4-412df21e362d"
/dev/vda3: UUID="e0421809-f014-4ea5-8183-fd96c8423be3" TYPE="swap" PARTUUID="a5d2758f-0a2c-4145-9c04-9b6ddce9b07c"
/dev/vda4: UUID="c50aefdd-bc0f-4761-a47f-60deadbc0f30" TYPE="xfs" PARTUUID="6e441755-2842-4746-8f24-8c54019c72b6"
/dev/sda1: UUID="f2151d94-6fb5-48af-af4f-b36c403d4247" TYPE="ext4"
/dev/sr0: UUID="2018-05-08-14-09-45-00" LABEL="CentOS 7 aarch64" TYPE="iso9660"
[root@arm64v8 ~]#
[root@arm64v8 ~]# blkid /dev/sda1
/dev/sda1: UUID="f2151d94-6fb5-48af-af4f-b36c403d4247" TYPE="ext4"
[root@arm64v8 ~]#
5.5.3、file 命令
[root@arm64v8 ~]# file -s /dev/sda1
/dev/sda1: Linux rev 1.0 ext4 filesystem data, UUID=f2151d94-6fb5-48af-af4f-b36c403d4247 (extents) (64bit) (large files) (huge files)
[root@arm64v8 ~]#
5.5.4、du 命令
du 命令用于评估文件的空间占用情况,它会统计每个文件的大小,统计时会递归统计目录中的文件,也就是说,它会遍历整个待统计目录,所以统计速度上可能并不理想。
du [OPTION]... [FILE]...
选项说明:
-a, --all:列出目录中所有文件的统计信息,默认只会列出目录中子目录的统计信息,而不列出文件的统计信息
-h, --human-readable:人性化显示大小
-0, --null:以空字符结尾,即"\0"而非换行的"\n"
-S, --separate-dirs:不包含子目录的大小
-s, --summarize:对目录做总的统计,不列出目录内文件的大小信息
-c,--total:对给出的文件或目录做总计。在统计非同一个目录文件大小时非常有用。见下文例子。
-d,--max-depth:指定显示时的目录深度,默认会递归显示所有层次
--max-depth=N:只列出给定层次的目录统计,如果N=0,则等价于"-s"
-x, --one-file-system:忽略不同文件系统上的文件,不对它们进行统计
-X, --exclude-from=FILE:从文件中读取要排除的文件
--exclude=PATTERN:指定要忽略不统计的文件
- 上面的选项中,有些是不列出某些项,有些是不统计某些项,它们是不一样的。
- 如果要统计的目录下挂载了一个文件系统,那么这个文件系统的大小也会被计入该目录的大小中。
[root@arm64v8 ~]# du -sh /etc/
29M /etc/
[root@arm64v8 ~]#
[root@arm64v8 ~]# du -ah /tmp/
0 /tmp/.XIM-unix
0 /tmp/.font-unix
0 /tmp/.Test-unix
0 /tmp/.X11-unix
0 /tmp/.ICE-unix
4.0K /tmp/yum_save_tx.2021-06-10.09-43.sULMgF.yumtx
4.0K /tmp/a.txt
8.0K /tmp/
[root@arm64v8 ~]#
[root@arm64v8 ~]# du -h --max-depth=1 /usr/
78M /usr/bin
43M /usr/sbin
468M /usr/lib
155M /usr/lib64
238M /usr/share
0 /usr/etc
0 /usr/games
36K /usr/include
14M /usr/libexec
0 /usr/local
0 /usr/src
991M /usr/
[root@arm64v8 ~]#
[root@arm64v8 ~]# du -h --max-depth=1 --exclude=/usr/lib64 /usr
78M /usr/bin
43M /usr/sbin
468M /usr/lib
238M /usr/share
0 /usr/etc
0 /usr/games
36K /usr/include
14M /usr/libexec
0 /usr/local
0 /usr/src
837M /usr
[root@arm64v8 ~]#
5.5.5、df 命令
df 用于报告磁盘空间使用率,默认显示的大小是 1K 大小 block 数量,也就是以 k 为单位。
和 du 不同的是,df 是读取每个文件系统的 superblock 信息,所以评估速度非常快。由于是读取 superblock,所以如果目录下挂载了另一个文件系统,是不会将此挂载的文件系统计入目录大小的。
如果用 df 统计某个文件的空间使用情况,将会转而统计该文件所在文件系统的空间使用情况。
df [OPTION]... [FILE]...
选项说明:
-h:人性化转换大小的显示单位
-i:统计inode使用情况而非空间使用情况
-l, --local:只列出本地文件系统的使用情况,不列出网络文件系统信息
-T, --print-type:同时输出文件系统类型
-t, --type=TYPE:只列出给定文件系统的统计信息
-x, --exclude-type=TYPE:指定不显示的文件系统类型的统计信息
[root@arm64v8 ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
devtmpfs devtmpfs 16G 0 16G 0% /dev
tmpfs tmpfs 16G 0 16G 0% /dev/shm
tmpfs tmpfs 16G 20M 16G 1% /run
tmpfs tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/vda4 xfs 483G 1.2G 482G 1% /
/dev/vda2 xfs 1014M 108M 907M 11% /boot
/dev/vda1 vfat 200M 7.6M 193M 4% /boot/efi
tmpfs tmpfs 3.2G 0 3.2G 0% /run/user/0
[root@arm64v8 ~]#
[root@arm64v8 ~]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
devtmpfs 260971 349 260622 1% /dev
tmpfs 261119 1 261118 1% /dev/shm
tmpfs 261119 498 260621 1% /run
tmpfs 261119 16 261103 1% /sys/fs/cgroup
/dev/vda4 253159936 28461 253131475 1% /
/dev/vda2 524288 16 524272 1% /boot
/dev/vda1 0 0 0 - /boot/efi
tmpfs 261119 1 261118 1% /run/user/0
[root@arm64v8 ~]#
5.6、挂卸载文件系统
5.6.1、mount 命令
mount 用来显示挂载信息或者进行文件系统挂载,它的功能及其的强大,
它不仅支持挂载非常多种文件系统,如 ext/xfs/nfs/smbfs/cifs (win上的共享目录) 等,还支持共享挂载点、继承挂载点(父子关系)、绑定挂载点、移动挂载点等等功能。在本文只介绍其最简单的挂载功能。
mount 并非只能挂载文件系统,也可以将目录挂载到另一个目录下,其实它实现的是目录"硬链接",默认情况下,是无法对目录建立硬链接的,但是通过 mount 可以完成绑定,绑定后两个目录的 inode 号是完全相同的,但尽管建立的是目录的"硬链接",但其实也仅是拿来当软链接用。
以下是 ext 类文件系统的选项,可能有些选项是不支持其他文件系统的。
mount # 将显示当前已挂载信息
mount [-t 欲挂载文件系统类型 ] [-o 特殊选项] 设备名 挂载目录
选项说明:
-a 将/etc/fstab文件里指定的挂载选项重新挂载一遍。
-t 支持ext2/ext3/ext4/vfat/fat/iso9660(光盘默认格式)。 不用-t时默认会调用blkid来获取文件系统类型。
-n 不把挂载记录写在/etc/mtab文件中,一般挂载会在/proc/mounts中记录下挂载信息,然后同步到/etc/mtab,指定-n表示不同步该挂载信息。
-o 指定挂载特殊选项。下面是两个比较常用的:
loop 挂载镜像文件,如iso文件
ro 只读挂载
rw 读写挂载
auto 相当于mount -a
dev 如果挂载的文件系统中有设备访问入口则启用它,使其可以作为设备访问入口
default rw,suid,dev,exec,auto,nouser,async,and relatime
async 异步挂载,只写到内存
sync 同步挂载,通过挂载位置写入对方硬盘
atime 修改访问时间,每次访问都修改atime会导致性能降低,所以默认是noatime
noatime 不修改访问时间,高并发时使用这个选项可以减少磁盘IO
nodiratime 不修改文件夹访问时间,高并发时使用这个选项可以减少磁盘IO
exec/noexec 挂载后的文件系统里的可执行程序是否可执行,默认是可以执行exec, 优先级高于权限的限定
remount 重新挂载,此时可以不用指定挂载点。
suid/nosuid 对挂载的文件系统启用或禁用suid,对于外来设备最好禁用suid
_netdev 需要网络挂载时默认将停留在挂载界面直到加载网络了。使用_netdev可以忽略网络正常挂载。如NFS开机挂载。
user 允许普通用户进行挂载该目录,但只允许挂载者进行卸载该目录
users 允许所有用户挂载和卸载该目录
nouser 禁止普通用户挂载和卸载该目录,这是默认的,默认情况下一个目录不指定user/users时,将只有root能挂载
- 一般 user/users/nouser 都用在 /etc/fstab 中,直接在命令行下使用这几个选项意义不是很大。
mount 应用举例
-
挂载 CentOS 的安装镜像到 /mnt
[root@arm64v8 ~]# mount /dev/cdrom /mnt
- 其实 /dev/cdrom 是 /dev/sr0 的一个软链接,/dev/sr0 是光驱设备,所以也可以用 /dev/sr0 进行挂载。
-
重新挂载
[root@arm64v8 ~]# mount -t ext4 -o remount /dev/sda1 /data1
-
重新挂载文件系统为可读写
[root@arm64v8 ~]# mount -t ext4 -o rw remount /dev/sda1 /data1
-
基于ssh挂载远程目录
如何基于 ssh 像 NFS 一样挂载远程主机上的目录?可以通过 sshfs 工具,该工具在 fuse-sshfs 包中,这个包在 epel 源中提供。
[root@brinnatt ~]# yum install epel-release -y [root@brinnatt ~]# yum install fuse-sshfs -y [root@brinnatt ~]# sshfs -p 7422 36.158.226.101:/ /mnt/ The authenticity of host '[36.158.226.101]:7422 ([36.158.226.101]:7422)' can't be established. ECDSA key fingerprint is SHA256:URVNsjkxt5/51QYjJ/5K5POzrGOvDHkL51jqDaew7UY. ECDSA key fingerprint is MD5:34:c2:d9:36:d1:9a:ea:ba:45:14:22:2e:2a:66:f3:a2. Are you sure you want to continue connecting (yes/no)? yes root@36.158.226.101's password: [root@brinnatt ~]# ls /mnt/ bin dev Greatwall lib media opt root sbin sys usr boot etc home lib64 mnt proc run srv tmp var [root@brinnatt ~]#
-
挂载目录到另一个目录下。挂载目录时,挂载目录和挂载点的 inode 是相同的,它们两者的内容也是完全相同的
[root@arm64v8 ~]# mkdir /tmp/mpoint [root@arm64v8 ~]# touch /tmp/mpoint/{1,2,3}.txt [root@arm64v8 ~]# ls /tmp/mpoint/ 1.txt 2.txt 3.txt [root@arm64v8 ~]# [root@arm64v8 ~]# mkdir /tmp/point [root@arm64v8 ~]# touch /tmp/point/{a,b,c}.txt [root@arm64v8 ~]# ls /tmp/point/ a.txt b.txt c.txt [root@arm64v8 ~]# [root@arm64v8 ~]# mount --bind /tmp/mpoint/ /tmp/point/ [root@arm64v8 ~]# ls /tmp/point/ 1.txt 2.txt 3.txt [root@arm64v8 ~]#
-
查看某个目录是否是挂载点,使用 mountpoint 命令
[root@arm64v8 ~]# mountpoint /tmp/ /tmp/ is not a mountpoint [root@arm64v8 ~]# mountpoint /tmp/point/ /tmp/point/ is a mountpoint [root@arm64v8 ~]#
挂载的参数信息存放在 /proc/mounts(是/proc/self/mounts的软链接) 中,在 /proc/self/mountstats 和 /proc/mountinfo 里则记录了更详细的挂载信息。
[root@arm64v8 ~]# cat /proc/mounts | tail -6 hugetlbfs /dev/hugepages hugetlbfs rw,relatime,pagesize=512M 0 0 debugfs /sys/kernel/debug debugfs rw,relatime 0 0 /dev/vda2 /boot xfs rw,relatime,attr2,inode64,noquota 0 0 /dev/vda1 /boot/efi vfat rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=winnt,errors=remount-ro 0 0 tmpfs /run/user/0 tmpfs rw,nosuid,nodev,relatime,size=3342336k,mode=700 0 0 /dev/vda4 /tmp/point xfs rw,relatime,attr2,inode64,noquota 0 0 [root@arm64v8 ~]#
文件系统是需要驱动支持的,没有驱动的文件系统也无法挂载,Linux 中支持的文件系统驱动在 /lib/modules/$(uname -r)/kernel/fs 下。
[root@arm64v8 ~]# ls /lib/modules/$(uname -r)/kernel/fs/ binfmt_misc.ko cifs fat isofs mbcache.ko nfsd pstore xfs cachefiles cramfs fscache jbd2 nfs nls squashfs ceph ext4 fuse lockd nfs_common overlayfs udf [root@arm64v8 ~]#
5.6.2、挂载镜像文件
mount 是一个极其强大的挂载工具,它支持挂载很多种文件类型,其中就支持挂载镜像文件,其实它连挂载目录都支持。
[root@controller1 3.5.2_arm_greatwall]# mount Greatwall-aarch64-DVD-3.5.2-190918-c75.iso /mnt/
mount: /dev/loop0 is write-protected, mounting read-only
[root@controller1 3.5.2_arm_greatwall]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 3G 0 loop /mnt
sda 8:0 0 837.9G 0 disk
├─sda4 8:4 0 832.7G 0 part /
├─sda2 8:2 0 1G 0 part /boot
├─sda3 8:3 0 4G 0 part [SWAP]
└─sda1 8:1 0 200M 0 part /boot/efi
[root@controller1 3.5.2_arm_greatwall]#
5.6.3、umount 命令
umount 设备名或挂载目录
umount -lf 强制卸载
卸载时,既可以使用设备名也可以使用挂载点卸载。有时候挂载网络系统(如NFS)时,设备名很长,这时候可以使用挂载点来卸载就方便多了。
如果用户正在访问某个目录或文件,使得卸载一直显示 Busy,使用 fuser -v DIR 可以知道谁正在访问该目录或文件。
[root@controller1 ~]# fuser -v /mnt/
USER PID ACCESS COMMAND
/mnt: root kernel mount /mnt
[root@controller1 ~]#
使用 -k 选项 kill 掉正在使用目录或文件的进程,使用 -km 选项 kill 掉文件系统上的所有进程,然后再 umount。
[root@controller1 ~]# fuser -km /mnt/; umount /mnt/
5.6.4、开机自动挂载
通过将挂载选项写入到 /etc/fstab 中,系统会自动挂载该文件中的配置项。但要注意,该文件在开机的前几个过程中就被读取,所以配置错误很可能会导致开机失败。
其中最后两列,它们分别表示备份文件系统和开机自检,一般都可以设置为 0。由于能用的备份工具众多,没人会在这里设置备份,所以备份列设置为 0。
最后一列是开机自检设置列,开机自检调用的是 fsck 程序,所有有些 ext 类文件系统作为 "/" 时,可能会设置为1,但是 fsck 是不支持 xfs 文件系统的,所以对于 xfs 文件系统而言,该项必须设置为 0。
其实无需考虑那么多,直接将这两列设置为 0 就可以了。
5.6.5、修复错误
万一 /etc/fstab 配置错误,导致开机无法加载。一般是停留在 "Give root password for maintenance" 这样的界面,输入 root 密码进入系统,重新修改 /etc/fstab 文件,重启即可。
如果卡住没法进入系统,可以利用 grub 配置传入 rd.break 参数进入特权模式,修改 /etc/fstable 然后重启即可。
5.7、swap 分区
虽说个人电脑上基本已经无需设置 swap 分区了,但是在服务器上还是应该准备swap分区。
5.7.1、查看 swap
[root@arm64v8 ~]# free -h
total used free shared buff/cache available
Mem: 31G 224M 31G 35M 441M 28G
Swap: 15G 0B 15G
[root@arm64v8 ~]#
使用 mount/lsblk 等可以查看出哪个分区在充当 swap 分区。使用 swapon -s 也可以直接查看出。
[root@arm64v8 ~]# swapon -s
Filename Type Size Used Priority
/dev/vda3 partition 16712640 0 -2
[root@arm64v8 ~]#
5.7.2、添加 swap 分区
-
可以新分一个区,在分区时指定其分区的 ID 号为 SWAP 类型。
mbr 和 gpt 格式的磁盘上这个 ID 可能不太一样,不过一般 gp t中的格式是在 mbr 格式的 ID 后加上两位数的数值,如 mbr 中 swap 的类型 ID 为 82,在 gpt 中则是 8200,在 mbr 中 linux filesystem 类型的 ID 为 83,在 gpt 中则为 8300,在 mbr 中 lvm 的 ID 为 8e,在 gpt 中为 8e00。
-
格式化为 swap 分区:mkswap
[root@arm64v8 ~]# mkswap /dev/sda1 mkswap: /dev/sda1: warning: wiping old ext4 signature. Setting up swapspace version 1, size = 975808 KiB no label, UUID=9a96b5d9-70b4-4a70-a1d6-31ed99175b52 [root@arm64v8 ~]#
-
加入 swap 分区空间(swapon)
[root@arm64v8 ~]# swapon /dev/sda1 [root@arm64v8 ~]# free -h total used free shared buff/cache available Mem: 31G 225M 31G 35M 441M 28G Swap: 16G 0B 16G [root@arm64v8 ~]#
-
取消 swap 分区空间(swapoff)
[root@arm64v8 ~]# swapoff /dev/sda1 [root@arm64v8 ~]# [root@arm64v8 ~]# free -h total used free shared buff/cache available Mem: 31G 224M 31G 35M 441M 28G Swap: 15G 0B 15G [root@arm64v8 ~]#
-
开机自动加载 swap 分区
# 修改 /etc/fstab,加上一行 /dev/sda1 swap swap defaults 0 0