fdisk分区增删改查实战:MBR/GPT、扇区对齐与挂载生效
磁盘空间告急、给虚拟机挂了一块新盘要划成几个区、做实验要腾出一块 LVM 物理卷,这类场景在运维日常里几乎每周都会碰上。多数人的第一反应是敲fdisk,但真正上手时又会在"选 MBR 还是 GPT""结束扇区写 +2G 还是写 +2048M""改完分区表为什么lsblk里看不到新分区"这些问题上卡住。这篇内容就是围绕fdisk 分区的增、删、改、查这四件事展开的,从分区表在磁盘上的物理结构,一直讲到格式化、挂载、开机自动生效和脚本化批量操作。它面向的是刚接触 Linux 磁盘管理的新手,也适合那些平时只用parted或图形化工具、想把fdisk这条命令体系彻底吃透的从业者。所有命令都在 RedHat 9.0 环境下实测过,涉及参数取舍的地方我会说清楚为什么这么选,而不是只给一串可以抄的命令。
1. 先弄明白 fdisk 在磁盘上改的到底是什么
1.1 分区表的两种格式与 RHEL 9 的默认选择
很多人对fdisk的理解停在"它能分区",但不知道它改的其实只是磁盘开头或结尾那一小块"目录"。磁盘本身是连续的扇区序列,没有分区这个概念,是分区表告诉操作系统"第 A 扇区到第 B 扇区归 /dev/sdb1,第 C 到第 D 归 /dev/sdb2"。fdisk做的所有事情,本质上就是在编辑这张目录表,以及在写盘的那一刻把表交给内核去认。
RHEL 9 上这条命令由util-linux包提供,fdisk --version会显示 2.x 版本,它同时支持 MBR(在命令里叫dos)和 GPT 两种分区表。选哪种不是习惯问题,是硬约束:MBR 用 4 字节记录起始 LBA、4 字节记录分区长度,理论寻址上限是 2TiB,最多 4 个主分区;GPT 用 64 位 LBA 寻址,分区项默认 128 项,容量上限在现实里基本等同于磁盘本身的上限。RHEL 9 在 UEFI 引导下的系统盘必须是 GPT,因为需要一个 EFI System 分区;数据盘则两者都行,但我的建议是只要容量超过 2TiB 或者未来可能扩容到 2TiB 以上,一律直接上 GPT,别等到某天发现扩不上去再迁移数据。
这里有个容易被忽略的点:GPT 的分区表是双份的,主表在 LBA1,备份表在磁盘末尾的最后一个 LBA,两者带 CRC32 校验。所以在一台老盘上重新分区时,经常能看到The backup GPT table is not on the end of the disk这类提示,本质是磁盘被做过容量变更或者被 dd 过头部,备份表和主表对不上了。这种时候进入fdisk用g新建 GPT 分区表,或者用sgdisk -e把备份表挪到正确位置就行,不影响已有数据,因为没有改分区项内容。
注意:
o键是新建一张空的 MBR 分区表,g键是新建一张空的 GPT 分区表,这两个操作都会清空现有分区表。手滑敲下去再按w,分区项就没了。数据扇区还在,但系统认不出文件系统,恢复成本高得多。
1.2 扇区对齐这件事,比命令本身更重要
真正决定分区性能的,不是分区表类型,而是起始扇区是否对齐到物理存储的擦除块。机械硬盘的物理扇区是 512 字节还好说,但现代磁盘(尤其是 SSD 和 4Kn 盘)物理扇区是 4096 字节,闪存的擦除块更大。如果分区起点落在 4K 边界之外,一次 4K 的逻辑写会被拆成两次物理读改写,性能损失在小文件场景下能达到百分之几十,而且是长期的、隐蔽的。
历史原因在于 MBR 分区表本身占 512 字节,早期工具默认让第一个分区从第 63 扇区开始(因为磁道历史上是 63 扇区一个),63 乘 512 等于 32256 字节,不是 4096 的整数倍,天然错位。现代fdisk已经默认从 2048 扇区(正好 1MiB)起排,并且在你输入结束扇区时会尝试按 2048 对齐。你可以用fdisk -l输出里的Start列自查:只要是 2048 的整数倍,基本就没问题。
我在实操里的习惯是进fdisk之后先按一次u看当前单位,再按p看已有分区的起止值。如果一块盘上已有分区的起点是 63 或 2047 这种数,说明这张表是旧工具生成的,新建分区时千万不要沿用"接着上一个分区的结束扇区往后一个"这种思路,而是直接接受 fdisk 给出的默认起始值,让工具自己对齐。为了省几十个扇区把性能搭进去,完全不划算。
2. "查":上机第一件事是把磁盘信息看清楚
2.1 从 lsblk 到 fdisk -l 的快查组合拳
动刀之前必须先看清楚现状,这一步偷懒是后面所有事故的源头。我自己固定的一套顺序是lsblk -f看整体拓扑和文件系统,fdisk -l /dev/sdX看分区表细节,blkid看 UUID 和文件系统类型,df -hT看当前挂载关系和剩余空间。四条命令下去,一块盘的来龙去脉基本就清楚了。
lsblk的价值在于它以树形结构展示磁盘和分区的父子关系,加-f参数还能直接显示FSTYPE、UUID、MOUNTPOINT,一眼就能看出哪个分区已经格式化、挂在哪儿、用的是 XFS 还是 ext4。相比之下fdisk -l输出的是分区表原始视角,会告诉你每个分区的起止扇区、扇区总数、分区类型代码和磁盘的扇区大小(Sector size (logical/physical))。这两者信息互补,前者看"用了什么",后者看"划了什么"。
有一段特别值得留意:fdisk -l顶部会打印Disklabel type: gpt或dos,这就是判断分区表格式最直接的依据。另外Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors这行里的扇区总数,是后面手工计算分区边界的基数。我见过不少人在虚拟化环境里给盘加了容量,fdisk -l却还显示旧容量,那是因为 hypervisor 层加了,guest 内核没重新扫描,这时候需要触发一次 SCSI 总线扫描,而不是怀疑 fdisk 有问题。
lsblk -f fdisk -l /dev/sdb blkid /dev/sdb1 df -hT还有一种情况是盘根本没有出现在lsblk里。热添加的虚拟磁盘、外接存储,内核可能还没扫描到。可以执行echo "- - -" > /sys/class/scsi_host/host0/scan逐个 host 扫一遍,或者安装sg3_utils后用rescan-scsi-bus.sh。扫完再lsblk,新盘就出来了。这套流程我在虚拟机扩容和云主机挂盘的场景里用得最多。
2.2 进入交互模式后的 p、m、l 三个高频键
fdisk /dev/sdb进入交互模式后,屏幕会提示Command (m for help):。新手最容易慌的就是这一步,其实只要记住三个键就够用了:p打印当前分区表,m打印帮助菜单,l列出所有可用的分区类型代码。这三个键都是只读操作,敲错了也不会改任何东西。
p的输出比命令行fdisk -l更贴近交互语境,它会明确列出Device、Boot、Start、End、Sectors、Size、Type七列,还会提示Device does not contain a recognized partition table或者Partition table entries are not in disk order。后者是需要警惕的信号,意味着分区项在表里的排列顺序和物理位置不一致,某些老工具或引导程序可能处理不了,通常重建一次分区表或者用f修复(部分版本支持)能解决。
l键在 MBR 模式下会打印一份十六进制代码对照表,比如83 Linux、82 Linux swap / Solaris、8e Linux LVM;在 GPT 模式下则是另一份列表,包含Linux filesystem、Linux swap、Linux LVM、EFI System等条目以及它们对应的编号。不要死记这些编号,不同版本的util-linux列表顺序和编号都可能不同,每次按l看一眼更稳。这个习惯帮我避免过好几次把分区类型标错导致 LVM 工具识别不出来的问题。
提示:交互模式下任何时候都可以按
q退出且不保存任何改动。养成"改完先p复核,满意了再w"的节奏,比事后恢复省事一百倍。
3. "增":新建分区从规划到落盘
3.1 新建之前必须先算清的三件事
新建分区之前,我会先在纸上(或者终端里)算清楚三件事:这块盘还剩多少连续空间、新分区要多大、起始位置落在哪。这三件事任何一件含糊,都会导致建出来的分区用不了或者要推倒重来。
剩余空间看p输出里最后一行分区的结束扇区,以及磁盘总扇区数。比如总扇区 41943040,最后一个分区结束在 20971519,那从 20971520 往后就是空闲区,容量大约是把差值乘 512 字节。这里有个陷阱:fdisk 的默认起始扇区是"第一个可用扇区",而不是"最后一个分区结束扇区加一"。如果中间的某个分区被删过,默认起点可能落在中间的空洞里,这时候你按回车接受默认值,建出来的分区位置可能和预期完全不一样。我的做法是每次n之后,先看它给的默认起点是不是我想要的位置,再决定接受还是手动输入。
容量规划上,分区大小和文件系统强相关。XFS 只能扩不能缩,所以划 XFS 分区时宁可留点余量也别一次划满到边界,后续要腾空间只能删了重建。ext4 可以缩容,但缩容前必须先umount,再用resize2fs缩文件系统,最后才改分区大小,顺序错了就是数据灾。LVM 分区更简单,直接划成 PV 交给卷组,后面用lvextend灵活得多,所以现在我的习惯是除了/boot和 swap,其余空间一律划成一个 LVM 分区,把灵活性留在上层。
3.2 n 键建分区实操:MBR 与 GPT 的差异
按n之后,交互流程会因分区表类型不同而分岔。GPT 下只问分区号和起止位置,过程很直白;MBR 下会先问Partition type,让你选p(primary,主分区)还是e(extended,扩展分区),因为 MBR 最多只有 4 个主分区,超出就得用一个扩展分区去装逻辑分区,逻辑分区编号从 5 开始。
GPT 下建一个 2GiB 分区的完整过程大致是:按n,分区号接受默认,起始扇区接受默认,结束扇区输入+2G。fdisk 会回显Created a new partition 1 of type 'Linux filesystem' and of size 2 GiB。这里+2G这种写法是 fdisk 支持的容量后缀语法,K、M、G、T、P都行,也可以直接写扇区数。用后缀的好处是不用自己算除法,工具会替你换算并对齐结束位置。
MBR 下假设已经有 2 个主分区,再按n会提示Partition type: p primary (2 primary, 0 extended, 2 free),选p就是第 3 个主分区,选e就是扩展分区。扩展分区本身不存数据,它只是一个容器,装进去的叫逻辑分区。我见过有人把整块盘都划成扩展分区然后纳闷为什么格式化不了,就是没理解这一层。如果规划里主分区会超过 4 个,一开始就该把剩余空间全划成一个扩展分区,后面所有分区都建成逻辑分区。
fdisk /dev/sdb # Command (m for help): n # Partition number (1-128, default 1): 1 # First sector (2048-41943006, default 2048): 回车 # Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-41943006, default 41943006): +2G # Command (m for help): p # Command (m for help): w3.3 写盘生效与内核重读分区表
按下w之后 fdisk 会打印The partition table has been altered并调用 ioctl 通知内核重读。这时候大多数情况下lsblk就能看到新分区了。但有两种常见情况会让人以为操作失败:一是设备上有分区正被挂载或正在被 LVM 使用,内核拒绝重读,会提示Re-reading the partition table failed.: Device or resource busy;二是内核收到了通知但 udev 还没处理完,设备节点/dev/sdb1还没生成。
第一种情况的处理是先umount掉相关分区,必要时vgchange -an停掉卷组,再执行一次重读。重读的命令有几种,partprobe /dev/sdb最常用(来自parted包,系统没装就先dnf install parted),partx -u /dev/sdb只更新新增分区,blockdev --rereadpt /dev/sdb操作的是整个块设备。这几个在功能上有细微差异,partprobe会顺带触发 udev 事件,通常最省心。
第二种情况通常等一两秒就好,或者执行udevadm settle让 udev 队列跑完。如果还是看不到,用partx -a /dev/sdb加上udevadm trigger基本能解决。这些操作我在 RHEL 9 上反复试过,重启是最粗暴但永远有效的兜底方案,只是生产环境不可能为了一个分区表重读去重启,所以上面这套命令值得收藏。
注意:分区表写盘之后、格式化之前,如果这块盘之前被用过,务必要先
wipefs -a /dev/sdb1清掉旧文件系统残留签名。否则mkfs.xfs会提示appears to contain an existing filesystem而拒绝执行,加-f强上也有隐患。
4. "改":改分区类型、改盘符体系与改容量
4.1 t 键改分区类型标识
分区类型在 Linux 里不像在桌面系统那样被强制使用,内核并不看你标的是Linux filesystem还是Linux LVM,它只认分区里的文件系统签名。但类型标识并非无用,lvm、swapon、部分安装器和引导加载程序会参考这个标识做判断。比如你把一个分区标成Linux LVM然后用pvcreate,工具链配合起来更顺;反之标成普通文件系统再去建 PV,虽然也能成,但属于"不规范但能用"的状态。
改类型的操作是t加分区号,再输入类型编号。GPT 模式下会弹出一个很长的列表,建议先用l看一眼,找到Linux LVM或Linux swap对应的编号再输入。MBR 模式下则是十六进制代码,83是 Linux,8e是 LVM,82是 swap。
这里有个实用技巧:类型标识可以在分区建好之后随时改,不影响分区里的数据,因为它只是分区表里的一个字段。我曾遇到一块盘上已经有 LVM 数据,但分区类型被误标成了普通 Linux,pvs命令能识别出来但告警不断,用t改成8e再w写盘,问题就消失了,数据一点没动。
4.2 改分区编号的正确姿势
fdisk 没有"直接改分区号"的命令,d删掉再n重建是唯一路子。但这里有个很多老手都在用的技巧:删掉之后重建时,起始扇区手动填成和原来完全一样的值,结束扇区也填成和原来一样,这样分区在磁盘上的物理位置完全不变,里面的文件系统、UUID、数据全都保留,只是分区表中的编号变了。
举个例子,/dev/sdb1想变成/dev/sdb2(因为要插一个新盘在前面),流程是记下p输出里 sdb1 的 Start 和 End,d删掉它,n新建分区号填 2,起始填原来的 Start,结束填原来的 End,w写盘。然后partprobe,lsblk -f会看到/dev/sdb2带着原来的 UUID 和文件系统。因为/etc/fstab里用的是 UUID 而不是设备名,改号之后挂载完全不受影响——这正是我一直坚持用 UUID 挂载的原因之一。
需要提醒的是,GPT 模式下重建分区会生成新的分区 GUID(PARTUUID),如果有引导程序或fstab里写的是PARTUUID=,那就需要同步更新。单纯写UUID=的没有影响。
4.3 扩容:可以涨,但要看清文件系统脸色
改容量在 fdisk 里的做法同样是删了按新边界重建,因为分区表就是这么个结构。流程是d删掉目标分区,n重建,起始扇区保持原值,结束扇区填大一些,w写盘,partprobe。内核认到新分区表之后,分区变大了,但文件系统还是老的尺寸,需要再扩一次。
这一步的差别就出来了:XFS 用xfs_growfs /mountpoint,在线就能扩,不用卸载;ext4 用resize2fs /dev/sdb1,在线也能扩。两者都只能变大不能变小,其中 XFS 压根不支持缩小,ext4 支持缩小但必须卸载且步骤繁琐。这就是前面说的"划 XFS 要留余量"的原因。
在 LVM 场景下这套流程更丝滑:分区变大或者直接加一块新盘,pvcreate、vgextend、lvextend -r(加-r会自动调用对应的文件系统扩容命令),一条链下来,业务无感知。这也是我在 RHEL 9 上更推荐 LVM 的原因,fdisk 只负责划一块整洁的 PV,剩下的交给上层,省心。
5. "删":删除分区与误操作的止损
5.1 d 键删除与保存前最后一道关
d加分区号,分区表里对应那一项就被清掉了。注意这仅仅是清掉分区表项,磁盘上那个扇区范围内的数据一个字节都没动。所以删分区本身极快,快到你来不及反悔,这也是它危险的地方。好在 fdisk 的设计里,所有改动都堆在内存里,只有按w才会真正写盘,按q全部丢弃。
基于这个特性,我形成了一个固定动作:任何涉及删除的操作,d之后立刻按p复核,确认要删的确实是那个分区,然后再决定w还是q。曾经有一次多盘环境下我敲错了设备名,d删完按p一看发现清单对不上,直接q退出,零损失。如果当时手快按了w,就得走下面那套恢复流程了。
删除时还要注意一个结束条件:fdisk 会提示Partition X has been deleted。如果删的是扩展分区,里面的逻辑分区会一并从表里消失,提示信息会告诉你删掉了几个。删除之后再n新建,编号可能被复用也可能往后排,取决于分区表实现,不影响使用,但如果脚本里依赖固定设备名要留意。
5.2 误删之后还剩什么,怎么救
误删并且已经w写盘,先别慌,也别做任何写操作。数据还在原地,丢的只是"目录页"。恢复手段按投入从低到高排:最低成本是还记得原来的起止扇区,直接n重建,起始和结束填回原值,w写盘,partprobe,lsblk -f一看 UUID 还在,mount上去数据完好。这是最常见也最幸运的情况,靠的就是前面让你记下p输出的习惯。
记不得起止扇区时,可以用testdisk或者gpart这类工具扫描磁盘寻找文件系统签名,它们会推断出分区边界并给出重建建议。XFS 的超级块、ext4 的超级块都有固定特征,扫描识别率相当高,但这一步需要额外装包,而且扫描大容量磁盘耗时较长。
还有一种历史上很常用的土办法:dd if=/dev/sdb of=/root/sdb_mbr.bak bs=512 count=1提前备份 MBR 头 512 字节,出事之后dd if=/root/sdb_mbr.bak of=/dev/sdb bs=512 count=1写回去。这个办法只对 MBR 分区表有效,因为 MBR 分区表就在第一个扇区里;GPT 的主表和备份表加起来占了 34 个扇区,需要按 LBA 范围备份,用sgdisk --backup=更规范。我在做重要磁盘操作之前会顺手备份一份,几秒钟的事,关键时刻能救命。
6. 分区之后:格式化、挂载与开机自动生效
6.1 mkfs 参数选择与 XFS 的取舍
分区建好只是有了容器,要存东西还得铺一层文件系统。RHEL 9 的默认文件系统是 XFS,mkfs.xfs /dev/sdb1一条命令搞定,常用参数里-f强制覆盖已有文件系统,-L设置卷标,-b size=设置块大小(默认 4K,一般不用改)。XFS 的优势在于大文件和高并发写入表现好、在线扩容方便,代价是不能缩小,以及对元数据一致性的依赖让它在异常断电后的恢复时间比 ext4 长一些。
需要 ext4 的时候用mkfs.ext4 /dev/sdb1,参数上-L设置卷标,-m调整保留块百分比(默认 5% 给 root 预留,数据盘可以调到 1 甚至 0 省空间),-i调整 inode 密度。小文件特别多的场景(比如邮件队列、缓存目录)要提前把 inode 算够,否则会出现磁盘还有空间但提示No space left on device的经典故障。这一点在实际运维里踩坑率很高。
swap 分区不格式化,而是mkswap /dev/sdb1然后swapon /dev/sdb1。做 LVM 物理卷则是pvcreate /dev/sdb1。这三种"使用方式"互斥,一个分区只能用其中一种。
注意:
mkfs系列命令一旦执行,分区里的旧数据立即不可恢复。执行前用lsblk -f和blkid双重确认设备名,多盘环境下/dev/sdb和/dev/sdc敲错一个字母就是事故。
6.2 fstab 用 UUID 挂载与 SELinux 上下文
临时挂载用mount /dev/sdb1 /data就行,但重启就没了。要开机自动生效,得写/etc/fstab。这里我强烈建议用 UUID 而不是设备名,因为/dev/sdX的命名顺序取决于内核探测顺序,插拔一块盘、改一下 BIOS 顺序,设备名就可能变,用设备名写的 fstab 轻则挂错位置,重则系统起不来。UUID 是文件系统创建时生成的,跟设备名无关,稳定得多。
获取 UUID 用blkid /dev/sdb1或lsblk -f,然后在 fstab 里写上一行,格式是UUID=xxxx /data xfs defaults 0 0。这里六个字段依次是设备、挂载点、文件系统类型、挂载选项、dump 标记、fsck 顺序。XFS 的 fsck 顺序建议写 0,因为 XFS 用的是日志恢复不靠传统 fsck。
改完 fstab 之后有个关键验证动作:先mount -a试挂,没报错说明语法和路径都对;然后systemctl daemon-reload让 systemd 重新生成挂载单元,因为 RHEL 7 以后 fstab 是由 systemd 的生成器转换成 mount unit 的,不重载可能导致umount或systemctl status看到的状态不一致。最后findmnt /data确认挂载点和类型正确。
SELinux 这一层容易被忽略。在/下新建目录挂载数据盘,不带正确的安全上下文时,服务进程访问会被拒绝,日志里是Permission denied,但ls -l看着权限一切正常。处理办法是用semanage fcontext给挂载点定义一个合适的类型,或者干脆把数据盘挂在/srv、/var/lib/xxx这类已有标准上下文的位置。临时验证可以chcon -Rt httpd_sys_content_t /data,但重启或 relabel 之后会丢。restorecon -Rv /data用来把上下文恢复成策略规定的值,配合semanage fcontext -a一起用才是持久方案。
7. 非交互玩法:备份、还原与批量建分区
7.1 用 sfdisk 备份和克隆分区表
sfdisk和fdisk同属util-linux,前者是为脚本设计的。sfdisk -d /dev/sdb会把当前分区表导成一段纯文本,格式清晰,起始扇区、大小、类型、UUID 一目了然。把这段文本重定向到文件就是一份完美的分区表备份。恢复时把文件喂回去:sfdisk /dev/sdb < sdb_table.bak。
这个玩法在批量装机场景里价值极高。想象你有一批同型号的机器要配相同的磁盘布局,只要在一台机器上手工调好,导出分区表,剩下的全部用sfdisk灌进去,几秒一台。比起每台都进fdisk交互按半天,效率和一致性不在一个量级。
sfdisk还有几个常用的开关:-l查看(输出比 fdisk 友好)、-F修复分区表、--delete删掉所有分区。要注意新旧版本参数有些变化,RHEL 9 上的版本用sfdisk -d导出、sfdisk /dev/sdb < file导入就行,不需要额外开关。
7.2 脚本化建分区与自动化场景
fdisk本身也能非交互用,办法是把操作序列通过标准输入喂进去。比如要在一块空盘上建一个占满全盘的分区,可以这样写:
echo -e "g\nn\n1\n\n\nw" | fdisk /dev/sdb sleep 1 partprobe /dev/sdb udevadm settle mkfs.xfs -f /dev/sdb1g建 GPT 表,n新建,分区号 1,起始和结束都回车接受默认,w写盘。中间的空行就代表"按回车用默认值"。这种写法在初始化脚本里非常常见,但脆弱性也很明显:fdisk 的交互提示在不同版本间可能有细微差异,回车次数一旦对不上,后面的输入就会错位,最坏情况是意外写盘。所以脚本里用它之前,先在测试环境把输出录一遍,确认提示序列完全吻合。
更稳的替代方案是用parted的--script模式(parted -s /dev/sdb mklabel gpt mkpart primary xfs 0% 100%)或者直接sgdisk。这两者对非交互的支持更正式,错误处理也更清晰。我的原则是:一次性手工操作上 fdisk,脚本化和批量场景用 sfdisk / parted / sgdisk。不是说 fdisk 不能脚本化,而是它的定位就是交互工具,硬拿它做批处理属于用错场景。
8. 常见问题与排查速查
8.1 问题速查表
下面这张表是我这些年遇到的问题里出现频率最高的,基本覆盖了 90% 的现场情况。
| 现象 | 大概率原因 | 处理方式 |
|---|---|---|
w之后提示Device or resource busy | 目标设备上有分区被挂载或占用 | umount相关分区,必要时vgchange -an,再partprobe |
分区表改完lsblk看不到新分区 | 内核未重读 / udev 未处理完 | partprobe /dev/sdX、partx -u、udevadm settle |
mkfs.xfs拒绝执行 | 分区上有旧文件系统签名 | 先wipefs -a /dev/sdX1清除签名 |
提示does not start on physical sector boundary | 分区起点未 4K 对齐 | 删除重建,起始扇区用默认值或手动填 2048 的倍数 |
磁盘实际容量变大但fdisk -l显示还是旧的 | 内核未重新扫描块设备 | 重扫 SCSI 总线或重启,云环境需先在控制台扩容再重扫 |
| 开机卡在 emergency mode 提示 fstab 失败 | fstab 中设备 UUID 写错或挂载点不存在 | 进救援模式注释掉问题行,核对blkid输出 |
| 挂载成功但服务读不到文件 | SELinux 上下文不对 | restorecon -Rv配合semanage fcontext修正标签 |
磁盘还有空间却报No space left on device | inode 用尽 | df -i确认,重建文件系统时调大 inode 数量 |
| 提示备份 GPT 表不在磁盘末尾 | 磁盘容量变更后未同步备份表 | sgdisk -e /dev/sdX或g重建分区表 |
新增盘不在lsblk里 | 内核未发现新设备 | 扫描 SCSI 主机或rescan-scsi-bus.sh |
8.2 几条踩坑经验
第一个经验是关于设备名的不确定性。同一台机器上插不同的盘,/dev/sdb和/dev/sdc可能下次开机就换位置了。做操作之前用lsblk看一下容量和型号确认是目标盘,比只盯设备名靠谱。生产环境里我基本用/dev/disk/by-id/下的稳定软链接来定位磁盘,避免"以为在改数据盘结果在改系统盘"这种灾难。
第二个经验是关于"看起来像成功"。fdisk写盘后打印的The partition table has been altered只代表写到了磁盘上,不代表内核认到了。我形成反射的做法是每次w之后立刻lsblk,看不到新分区就partprobe再来一次,直到lsblk里出现才继续下一步。中间任何一个环节跳过,后面mkfs就会报设备不存在,排查起来反而绕远路。
第三个经验是别在挂载状态下改分区表。虽然内核支持重读,但挂载中的分区表变更在极端情况下可能让内核状态混乱,出现文件系统只读、目录列不出来这类现象。正规流程是先umount,再改表,再partprobe,再mount。如果实在不能停业务,那就考虑用 LVM 在线扩容,而不是在裸分区上折腾。
第四个是习惯性备份。分区表本身很小,备份成本几乎为零,但带来的心理安全感巨大。MBR 表用dd备份头 512 字节,GPT 表用sgdisk --backup=/root/sdb_gpt.bak /dev/sdb,一分钟都不用。我现在的做法是每台机器在完成磁盘规划之后,把分区表和lsblk -f的输出各存一份到/root/diskinfo/下,命名带上日期。几个月后回来排查问题,有这份快照能省掉大量猜测。
最后说个小技巧:fdisk里n建分区时,结束扇区除了写+2G,还可以写+100%FREE把剩余空间全用上,或者写-1G表示"从末尾倒数留 1GiB 空闲"。这几个写法在划分"留一点余量"的磁盘时特别好用,不用自己算减法。用得顺手之后,建分区这件事基本就是十几秒的事。