
1. 先搞懂 partx 到底解决什么问题1.1 分区表中的“两张表”概念刚接触 Linux 磁盘管理的人十有八九会被一个问题卡住用 fdisk 给磁盘分好区分区信息也正常写入了但系统就是不认lsblk看不到新分区fdisk -l却能看见。这时候很多人下意识就重启服务器或者一脸懵地到处搜索“为什么分区不生效”。其实这不是系统坏了也不是分区建错了而是你踩中了 Linux 磁盘子系统的经典机制问题。Linux 内核管理分区靠的是“两张表”。第一张是存在磁盘上的物理分区表由 fdisk、parted 这类工具负责读写它描述的是“这块盘上应该有哪些分区”可以理解为写在纸上的合同。第二张才是内核自己内存里维护的分区状态表记录的是“当前已经加载、可用的分区设备节点”相当于系统已经把合同内容录入到自己的管理系统里并生成了/dev/sda1、/dev/sdb2这样的设备文件。问题就出在这里fdisk 写完第一张表之后并不会自动通知内核“合同更新了”。如果这块盘在系统启动后才插上或重新分区内核内存里还是旧的状态自然看不到新分区。过去的方式是重启让内核重新初始化或者用partprobe通知内核重新读取。而partx这个命令就是专门干这件事的——它直接操作内核的分区状态表让你不重启就能完成分区刷新。1.2 partx 和 fdisk、partprobe 的分工差异很多人第一眼看到partx会觉得它和 fdisk 是同类工具其实它们分工完全不同。fdisk、parted 是“编辑磁盘分区表”的工具作用对象是磁盘上的数据结构而partx是“管理内核分区状态”的工具作用对象是内核的BLKPG接口和sysfs。再说细一点。partx可以做的事情包括让内核重新读取磁盘分区表并生成对应的分区设备节点对应参数-aadd让内核删除某个或全部分区设备节点对应参数-ddelete直接读磁盘上的分区表并格式化输出不碰内核状态对应参数-sshow只针对指定编号的分区操作而不是全盘处理对应参数-n或--nr。这个定位非常清楚它是内核和磁盘分区表之间的“传话人”。用大白话说fdisk 负责改合同partx负责把合同内容同步给管理系统。而partprobe是老牌的“刷新”工具和partx -a有点类似但它有个明显的短板——拿到一部分分区表异常或设备占用的情况下会直接失败而且它是整盘刷新没有“只加第三个分区”这种精细操作。实际用下来partx更灵活出错信息也更明确。遇到需要精细控制、脚本化处理的场景我基本都会优先选partx。有一类特殊场景partx是不可替代的在容器里、chroot 环境里或者某些没有 udev 服务的精简系统上磁盘热插拔后分区设备节点不会自动生成这时候partx -a是手动补设备节点最可靠的手段。这一点后面实操部分会详细讲。2. 核心参数与语法拆解2.1 命令格式与最常用的几个参数partx属于 util-linux 套件几乎所有主流发行版都自带不需要额外安装。命令基本格式是partx [选项] [设备名]我工作中用到最多的参数就这几个参数作用典型场景-a/--add通知内核添加磁盘上的全部分区设备节点新建分区后免重启刷新-d/--delete通知内核删除分区设备节点删除分区或准备重新分区-s/--show只显示磁盘的分区列表不修改内核状态查看分区表、脚本解析输出-n/--nr指定分区号或分区范围只操作第一个分区或某一段区间-o/--output指定输出列类似 lsblk 的 -o脚本里提取特定字段-P/--pairs以KEYvalue键值对格式输出脚本中循环解析-g/--noheadings输出不打印表头纯数据输出-t/--type指定分区表类型如 gpt、dos系统无法自动识别类型时手动指定-v/--verbose显示详细过程信息排查刷新失败原因-b/--bytes以字节为单位打印 SIZE 字段计算容量时避免单位歧义还有几个不常用但我提一下--raw原始输出、--list等价于-s的别名、-r在旧版本里代表 raw。不同发行版的 util-linux 版本不同个别参数行为略有差异用之前最好partx --help快速确认一下你机器上的版本。2.2 理解 --nr 的分区号语法--nr这个参数是新手最容易被劝退的地方因为它有一个反直觉的语法分区号是从 1 开始编号但允许写成m:n这样的范围而且m和n都是可以省略的。看几个例子你就明白了# 只添加第 1 个分区 partx -a --nr 1 /dev/sdb # 添加第 1 到第 3 个分区 partx -a --nr 1:3 /dev/sdb # 添加从第 2 个分区到最后一个分区 partx -a --nr 2:-1 /dev/sdb # 只看最后一个分区 partx -s --nr -1:-1 /dev/sdb这里的-1不是负数的分区号而是“最后一个分区”的意思。因为分区号永远是正整数所以-1被约定为边界符号。这套语法初看别扭但你写过几次脚本后就会觉得它其实非常强大尤其是“从第 N 个到最后一个”这种表达在不知道磁盘上一共有几个分区的情况下非常有用。另外注意--nr必须和-a、-d、-s其中一个搭配使用单独使用没有任何意义。还有一个容易被忽略的点partx -a --nr 1 /dev/sdb指定的是“哪几个分区需要让内核加载”但如果第 1 个分区对应的/dev/sdb1已经存在partx会跳过或报错不会像你期待的那样“重新加载一次”。后面排错章节我会展开讲这个坑。3. 实操过程与核心场景演示3.1 场景一新建分区后免重启刷新内核状态这是partx最经典的使用场景。假设你给一台运行中的服务器新加了一块云硬盘/dev/sdb然后用 fdisk 创建了一个 100GB 的分区fdisk /dev/sdb # 交互操作n - p - 1 - 回车 - 回车 - w这时fdisk -l /dev/sdb能看到分区表里有/dev/sdb1但lsblk里没有因为内核根本不知道这个分区的存在。处理方式就是partx -a /dev/sdb执行完一般没有任何输出没有消息就是好消息此时再看lsblklsblk /dev/sdb # NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT # sdb 8:16 0 100G 0 disk # └─sdb1 8:17 0 100G 0 part分区设备节点出现了下面就能正常mkfs.ext4 /dev/sdb1、mount /dev/sdb1 /data了。我这个流程看着简单但有几个操作习惯是我踩坑后形成的值得说一下。执行partx -a之前先用partx -s /dev/sdb确认内核能否正常解析分区表如果能正确列出分区说明磁盘上的分区表结构没问题问题纯粹是内核没加载这时候-a成功率极高。如果partx -s输出的分区表是空的、或者直接报错那就说明 fdisk 写入可能有问题后面刷了也是白刷。3.2 场景二删除分区时用 partx 清理内核状态删除分区的操作比添加更容易遇到“设备忙”问题。有人习惯直接用 fdisk 里的d命令删掉分区然后发现/dev/sdb1这个设备节点还在lsblk依然能看见。这是因为 fdisk 只改了磁盘上的分区表内核里的旧记录还没清掉。正确的清理姿势是先确认分区没有被挂载或使用然后执行umount /dev/sdb1 partx -d --nr 1 /dev/sdbpartx -d会通知内核移除对应的分区设备节点。如果你要删除全部分区记录可以简化为partx -d /dev/sdb这个命令在重新分区的场景里特别有用。我通常的做法是先用partx -d清掉内核里的旧分区状态再跑 fdisk 或 parted 重新写分区表最后用partx -a重新加载。这一套操作下来完全不需要重启也不会出现“新旧分区错位”的情况。我自己还经历过一种情况由于没有先删旧分区记录就直接用 fdisk 重写了分区表结果新的分区号和旧的设备节点对不上比如新表里第 1 个分区大小变了但/dev/sdb1设备节点的容量还是旧值mkfs 的时候直接写到了错误的size里去。这种问题如果没意识到排查起来非常痛苦。养成“先partx -d再改表再partx -a”的习惯就可以完全避免。3.3 场景三用 partx -s 做分区信息查询与脚本采集partx -s的行为和fdisk -l、lsblk都有点像但它有个别人替代不了的优势——输出格式高度可定制而且不改变内核状态纯粹是个“读”操作。这在脚本里非常好用。举个例子我想知道/dev/sdb第一个分区的起始扇区方便判断分区是否对齐partx -s -o NR,START,SECTORS /dev/sdb输出类似NR START SECTORS 1 2048 20971520如果想去掉表头、改成键值对方便在 bash 脚本里获取partx -s -g -P -o NR,START,SECTORS /dev/sdb输出NR1 START2048 SECTORS20971520然后就可以配合 shell 循环或awk解析。这是一种非常干净的数据管道比从 fdisk 的交互输出里抓文本舒服多了。我们团队有一个磁盘巡检脚本就是每分钟用partx -s -o NR,SIZE -b扫描所有磁盘分区记录是否有分区表变动再配合监控告警。用 fdisk 的文本抓取方式做同样的事解析成本高且容易误判而partx列结构稳定格外适合这种场景工程。补充一个适合运维的细节partx -s --type gpt /dev/sdb可以显式指定分区表类型。系统里分区表标志损坏、或者磁盘同时存在 MBR 和 GPT 保护性引导时partx可能无法自动判断手动指定类型能绕过部分误判。3.4 场景四脚本化加盘与扩容的标准流程把前面的操作串起来就形成一个非常实用的脚本化流程。比如给虚拟机新加一块 200G 数据盘并自动完成分区、刷新、格式化、挂载可以写出这样的执行序列# 1. 清理内核中的旧分区状态如果有的话 partx -d /dev/vdb 2/dev/null # 2. 写分区表创建 1 个分区占满整个磁盘 printf n\np\n1\n\n\nw\n | fdisk /dev/vdb # 3. 让内核读取新分区表并创建设备节点 partx -a /dev/vdb # 4. 格式化和挂载 mkfs.ext4 /dev/vdb1 mkdir -p /data mount /dev/vdb1 /data # 5. 写入 fstab 前先验证 UUID blkid /dev/vdb1这里有个要点是第 2 步的 fdisk 自动应答。printf管道输入的方式可以非交互创建分区但我建议不要在生产环境盲目照抄因为不同版本的 fdisk 对输入的解读存在细微差异。更稳妥的方式是先手动做一遍确认参数无误后再把固定的输入序列固化为脚本。另外在这个流程里partx -d前面的2/dev/null不是可有可无的。如果/dev/vdb本来就没有分区设备partx -d会报“partition is not defined”之类的提示但这并不影响后续流程所以把错误信息吞掉是合理的。还有一点要特别提醒对整块盘做partx -a时如果磁盘上已经有一些分区设备节点存在partx会跳过已存在的节点并不会报致命错误。但如果你期望它强制重建就达不到目的了。建议在关键操作前先确认当前状态lsblk /dev/vdb。4. 常见问题与排查技巧实录4.1 分区刷新失败的高频原因与定位流程用partx报错的情况其实就那几种。我整理了几个月来在群里被问得最多的问题基本可以对照自查。报错一partition(s) already defined这几乎是我见过最多的错误提示出现在磁盘上已经有分区设备节点的情况。比如你执行partx -a /dev/sdb如果/dev/sdb1已经存在partx就会跳过并打印类似信息。解决办法很简单先清理再添加partx -d /dev/sdb partx -a /dev/sdb或者用精确范围partx -d --nr 1 /dev/sdb partx -a --nr 1 /dev/sdb这个场景在重新分区、扩容后尤其常见。我自己的习惯是使用精确范围避免误删不该动的分区。报错二device is busy这说明有进程或挂载点正在使用该分区。删除或刷新分区前必须先释放资源umount /dev/sdb1 lsof /dev/sdb1lsof的输出会告诉你哪个进程还占用着设备确认无误后再操作。运维经验里有个经典坑你有 LVM、swap 或者 Docker 的 volume 挂载在上面umount后依然显示 busy那是因为占用进程还活在内存里。先停掉相关服务再操作比较稳妥。报错三failed to read partition table这个错误通常出在磁盘的分区表损坏、或者分区表类型无法被自动识别时。可以把排查重点放在三方面用fdisk -l /dev/sdb看物理分区表是否正常用partx -s --type gpt /dev/sdb或--type dos手动指定类型测试是否为检测逻辑问题检查磁盘是否有 RAID 卡或 DM 映射某些虚拟磁盘扇区大小特殊如 4K nativefdisk默认参数不对也会导致分区表写入异常。我之前遇到过一台物理机新加盘在 RAID 控制器下初始化为 4K 扇区用 fdisk 分区时忘了设置对齐导致分区起始扇区不是 8 的整数倍partx解析报错。后来调整fdisk的扇区参数重新分区问题解决。遇到这个报错优先怀疑物理层面的参数而不要一开始就怪partx本身。4.2 使用 partx 的一些实战心得与习惯建议根据个人经验我归纳了下面几条“别人不会写在 man page 里的心得”供你参考第一命令执行前先“读”后“写”。任何操作之前先partx -s看看当前分区表是否能被正确解析再决定要不要-a或-d。这就像改代码之前先编译一下确认基线是好的再动刀能省掉很多不必要的排查时间。第二脚本里尽量用--nr精确到分区号。裸用partx -a或partx -d的结果取决于磁盘上已有的分区设备节点状态。在一个被人手动操作过的环境里不加--nr的行为可能和预设不一致。比如你只想刷新第 3 个分区但-a /dev/sdb因为第 1、2 分区已存在而跳过第 3 分区其实被成功添加但你却不知道哪一步起了作用。这种不确定性在自动化场景里是隐患。第三partx不会修改磁盘上分区表的数据。它只是让内核同步状态。如果你在 fdisk 里写完分区表又后悔了想恢复原状partx帮不了你。磁盘上的数据要靠备份内核状态才靠partx。这个边界搞清楚很多混淆就不会发生。第四在日常操作中可以把partx和lsblk配合起来形成固定动作partx -s看物理表lsblk看内核态。偶尔遇到两边不一致的情况不用慌这恰恰说明这张盘正处于“状态待同步”的中间阶段用partx -a或-d对齐即可。最后说一个容易被人忽略的小技巧。如果你在某个精简容器镜像里跑脚本发现partx没有安装可以试一下apt-get install util-linux或者yum install util-linux补装。很多裁剪过的镜像把 util-linux 精简掉了而partx正是这个包里的一员。在没有 udev 或者/dev由容器运行时管理的环境里partx -a往往是手动补设备节点的唯一可行方式连partprobe都可能不可用。这一点在调试某些自定义初始化镜像、或者处理磁盘设备节点缺失问题的时候能省下大量折腾时间。