news 2026/10/23 1:37:47

Linux Swap在线扩容全攻略:文件、LVM与分区实操

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux Swap在线扩容全攻略:文件、LVM与分区实操

凌晨两点被监控告警叫起来,登录服务器一看,Swap 使用率 98%,内存也快见底了。这种时候最怕的就是手里没有一套稳妥的“在线扩容”方案——不能重启,不能影响正在跑的业务,最好能在几分钟内把 Swap 空间撑大。这活儿我干过不止一次,踩过不少坑,今天把 swap 在线扩容的方法完整梳理一遍。从判断当前 swap 形态开始,到 swap 文件、LVM 逻辑卷、物理分区三种场景的实操步骤,再到 swapoff 的隐藏风险、优先级调整、开机自启这些细节,一次性讲透。

1. 动手之前先搞清楚你手上的swap是什么形态

很多人上来就敲命令,敲了一半发现报错,根本原因是连自己机器上跑的是哪种 swap 都没搞清楚。swap 在 Linux 里一共有三种存在形态:独立的 swap 分区、LVM 逻辑卷上的 swap、以及一个普通文件作为 swap。三种形态的扩容方式完全不同,搞混了轻则白忙活,重则把系统搞到起不来。

1.1 三种形态一眼分辨

最简单的判断方法就一条命令:

swapon --show

输出里 NAME 和 TYPE 两列是关键。TYPE 显示partition的是物理分区,显示file的是文件型 swap,LVM 逻辑卷在部分发行版里会直接显示lvm,但有些系统显示的还是partition。为了确认,再用lsblk -f看一眼设备全貌,如果某个设备挂在vg-开头的卷组下面,那基本就是 LVM 形态没跑了。

这里有个很容易忽略的细节:free -h只能看到总量,看不出形态。很多云主机默认就是文件型 swap,路径通常是/swapfile或者/swap.img。物理机上最常见的则是独立分区/dev/sda3之类。LVM 形态常见于自建机房的机器,路径一般长这样:/dev/mapper/vg_swap-lv_swap。

把那台机器的现状彻底看清楚,后续选方案才有依据。建议顺手把这几条都跑一遍:

free -h swapon --show blkid | grep -i swap df -h

最后一条df -h是为了确认根分区或者/var目录有没有足够的剩余空间。如果打算走文件型 swap 路线,空间不够一切都是空谈。

1.2 在线扩容的本质:加新比改老更稳

“在线扩容”这四个字本身有歧义。严格意义上的实时扩容,指的是不重启、不中断业务、在当前系统运行状态下把可用 swap 总量变大。对于文件型 swap,你完全不需要动旧的 swap 文件,直接新建一个大文件,格式化后启用,总量立刻变大——这才是真正零风险的在线扩容。

但如果你非要“扩展现有的 swap 区域本身”,那对不起,swap 的格式是裸设备,没有类似 resize2fs 那样的在线调整工具。你必须把这个 swap 停掉再重建,而这个“停掉”的动作就叫 swapoff。swapoff 不是随便敲的,它有风险,后面我会专门开一节细讲。

所以我的核心观点先放在前面:在线扩容首选“新增文件/新增强度”,不要去“改老卷大小”。你保留原来的 swap 不动,新增一个 8G 的 swap 文件,通过优先级设置让系统优先使用新的大空间,旧空间慢慢就腾出来了。整个过程没有任何一个瞬间是 swap 容量减少的,业务完全无感。

2. swap文件扩展:五分钟操作,适用大多数云主机

文件型 swap 是云服务器上最主流的形态,也是在线扩容最友好的场景。原因很简单:扩容一个文件比扩容分区表容易一万倍。即使你的系统目前用的是 swap 分区,只要磁盘上有空间,我一般也建议直接新建 swap 文件来补充,而不是去动分区。下面按完整步骤走。

2.1 创建大文件:dd还是fallocate

创建 swap 文件最常见的是两个命令:fallocate和dd。两者的区别值得说道说道。

# 方法一:fallocate,瞬间完成 fallocate -l 8G /swapfile1 # 方法二:dd,慢但稳 dd if=/dev/zero of=/swapfile1 bs=1M count=8192 status=progress

我踩过坑的地方就在这里。fallocate分配的是“预留空间”,并没有真正写入数据,这在个别文件系统上会出问题。最典型的现象就是mkswap时提示swapfile has holes,然后swapon直接拒绝启用。我在某云主机的根文件系统(xfs)上真实遇到过。所以我在生产环境上的规则很简单:

  • ext4 上用 fallocate 基本没问题,但保险起见我仍然用 dd
  • xfs、btrfs 上不要用 fallocate 创建 swap 文件,大概率翻车
  • dd 慢归慢,但它真正把磁盘块写了一遍,绝对不会有 holes 问题

如果你用 dd 创建 8G 文件嫌慢,有个折中:用dd配合status=progress观察进度,实测在普通 SSD 上写 8G 也就十几秒,机械盘稍微慢一点,但完全可以接受。

文件创建完之后,强烈建议立刻改权限。swap 文件里保存的是内存里换出来的数据,可能有敏感信息,权限必须是 600:

chmod 600 /swapfile1

2.2 格式化、启用、持久化一条龙

接下来把文件格式化成 swap 格式并启用:

mkswap /swapfile1 swapon /swapfile1

做完之后用free -h或者swapon --show确认,你就会发现 Swap 总量明显变大了。这一步完成,其实已经算是扩容成功——不需要重启,当前正在跑的进程完全不受影响。

但这里必须强调:没写进 /etc/fstab 的 swap,重启后会丢。很多新手在这个环节掉坑里:今天扩容成功了,下个月重启发现 swap 又变回去了。持久化配置这样写:

echo '/swapfile1 none swap sw 0 0' >> /etc/fstab

两个细节值得说:

第一,可以用 UUID 代替路径。mkswap之后用blkid /swapfile1能看到这个文件的 UUID,写成UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx none swap sw 0 0更稳。路径写法的风险是如果哪天文件被误删,开机时会卡在 swap 等待上;UUID 同理。更稳妥的做法是给 fstab 行加nofail选项:

echo '/swapfile1 none swap sw,nofail 0 0' >> /etc/fstab

加了这个选项,哪怕文件出问题,开机最多打一条警告,不会卡住系统。生产环境我必加。

第二,fstab 修改后不要急着重启验证。用swapon -a手动挂载所有 fstab 里的 swap 条目,能成功就说明配置没问题。这个命令防呆效果极好。

2.3 想替换旧swap?先学会安全交换

新增文件扩容是最佳路线,但有些场景你确实需要把旧的 swap 替换掉。比如原来某个 swap 文件才 1G,你想把它回收,换成 8G 的新文件。这时候就必须swapoff /swapfile把旧的停掉。

安全交换的完整动作是这样的:

# 1. 先确认内存是否足够 free -h # 2. 把旧的 swap 停掉,这一步看 SwapUsed 是多少 swapoff /swapfile # 3. 删除旧文件或原地重建 rm -f /swapfile # 4. 重建新的 dd if=/dev/zero of=/swapfile bs=1M count=8192 status=progress mkswap /swapfile swapon /swapfile

关键判断在第二步。用free -h看 Swap 那一行的 used 值,确保当前可用内存(available 列)比这个值大得多,再执行 swapoff。swapoff 的机制是把 swap 空间里的内容写回内存,内存撑不住就是灾难。我见过一台内存压力很大的机器执行 swapoff 之后,直接卡死,最后被 OOM killer 干掉了一个关键进程。

如果你的 swap used 很高、内存又紧张,不要硬上。正确姿势是:新增一个更大的 swap 文件并设高优先级(下面会讲),让系统把数据先“挪”到新空间,等到旧 swap 的 used 降到接近 0 再 swapoff,风险瞬间小很多。

3. LVM逻辑卷和物理分区的swap扩容

文件型 swap 讲完了,但还有相当多的服务器是用 LVM 逻辑卷或独立物理分区承载 swap。这两种场景麻烦一点,但也不是不能在线搞定,关键是步骤顺序不能错。

3.1 LVM场景:lvextend之后必须重建swap区域

LVM 最大的好处是卷可以热扩。如果 swap 跑在 LVM 逻辑卷上,扩容逻辑卷本身很简单:

# 先看卷组和逻辑卷名 lvs # 扩展逻辑卷,增加 4G lvextend -L +4G /dev/mapper/vg_swap-lv_swap

执行完lvextend之后,逻辑卷本身已经从 4G 变成 8G。但此时 swap 区域并不知道这件事,它内部还是旧大小。这是因为 swap 没有文件系统,不存在“扩展文件系统”这一步,你必须重新格式化 swap 区域:

swapoff /dev/mapper/vg_swap-lv_swap mkswap /dev/mapper/vg_swap-lv_swap swapon /dev/mapper/vg_swap-lv_swap

这里有一个绝对不能踩的坑:LVM 扩容后的设备路径是不会变的(除非你把逻辑卷删了重建),但如果你在 fstab 里用的是 UUID 而不是设备路径,那么mkswap之后 UUID 已经变了,必须去更新 fstab。用blkid查新 UUID 再改,否则重启必卡。

# 用这条查新 UUID blkid /dev/mapper/vg_swap-lv_swap

至于前面说的 swapoff 风险,LVM 场景同样适用。如果 swap 使用率不高,直接 swapoff 没毛病;使用率高的话,还是建议先把内存压力降下来再操作。

另外一个实用技巧:如果目标机器上有空闲的物理卷或者卷组剩余空间充足,你完全可以不扩展现有 swap 逻辑卷,而是新建一个逻辑卷作为额外的 swap。这样连 swapoff 都可以省掉:

lvcreate -L 8G -n lv_swap2 vg_swap mkswap /dev/mapper/vg_swap-lv_swap2 swapon /dev/mapper/vg_swap-lv_swap2

新增逻辑卷对现有逻辑卷完全没有影响,整个过程就是纯在线扩容,一次 swapoff 都不用执行。LVM 场景我强烈推荐这种做法。

3.2 非LVM物理分区的扩容:能做但不推荐

如果你的 swap 是一个物理分区,比如/dev/sda2,那扩容就麻烦得多。麻烦的核心在于分区表。你要扩大这个分区,通常得删除分区记录再重建一个更大的分区,起始扇区必须保持一致,结束扇区往后推。这一套操作一旦失误,影响到的不只是 swap 分区,而是整个磁盘的分区表。

我直接给结论:非 LVM 的物理 swap 分区,如果磁盘后面还有空闲空间,优先考虑新建一个独立 swap 分区,而不是去拉伸旧分区。新建分区的操作其实很常规,fdisk 里n新建,类型选 82(Linux swap),写完w保存,然后mkswap启用。整个过程比修改旧分区安全得多。

如果确实没有额外分区空间,只能拉伸旧分区,那标准流程是这样:

# 1. 停用 swap swapoff /dev/sda2 # 2. 用 parted 或 fdisk 调整分区,起始扇区不变,结束扇区扩大 # 3. 让内核重新读取分区表 partprobe /dev/sda # 4. 重新格式化 swap 并启用 mkswap /dev/sda2 swapon /dev/sda2

现实中还有一个更“离线”的场景:某些云平台上云盘扩容后,分区表的变化需要重启才完全稳定。所以物理分区 swap 的扩容,其实很难真正实现“完全在线”。这也是我把“尽量别走这条路”写在前面原因。

4. 在线扩容的边界条件和运维细节

前面讲了具体操作,这一节专门讲那些容易踩的边界和细节。很多人 swap 扩容做完了,当时一切正常,过几天出问题才想起来哪个细节没注意,说的就是这些。

4.1 swapoff不是随便敲的

我已经提了好几次 swapoff 的风险,这里展开讲透。

swapoff 的本质是把 swap 空间中的所有内容搬回物理内存。如果当前可用内存不够容纳这些数据,内核就会很痛苦:一边要腾内存,一边还要等 swap 里的数据搬回来,整个系统会拖到近乎卡死。更极端的情况下,内核会启动 OOM killer 杀掉进程来强制回收内存。

判断是否适合 swapoff,我常用的标准是:available 内存 > SwapUsed × 1.5 以上,且当前没有明显的内存增长趋势。比如 SwapUsed 只有 200M,available 有 6G,那 swapoff 毫无压力。反之 SwapUsed 有 15G,available 只有 4G,那你千万不要敲这个命令。

如果必须 swapoff 但内存又不够,有两个缓解手段:

第一,先清理页缓存。sync && echo 3 > /proc/sys/vm/drop_caches能释放很大一部分缓存内存,腾出空间给 swapoff 用。

第二,用“汤换水”的方式,先启用新的更大的 swap,把旧 swap 的优先级调低,让系统优先使用新空间。等旧 swap 里的内容被慢慢替换掉,used 降到很低之后,再 swoff 旧的。步骤大概是这样:

# 1. 新 swap 已启用,把新 swap 优先级调高 swapon -p 100 /swapfile1 # 2. 把旧 swap 优先级调低(需要先关闭再重新挂载,或者用 swapon --priority 重新挂?实际做法:先swapoff旧的再swapon -p -1 挂回旧,但这样还是有一次swapoff)

严格来说,这个“替换”过程必然要经历至少一次 swapoff。但区别在于:你是在新空间已经顶上、系统压力缓解后才去动旧的,而不是在内存告急时硬来。这个顺序不能搞反。

4.2 优先级、swappiness和fstab的隐藏坑

优先级是个很实用的参数。当系统里有多个 swap 设备时,内核按优先级从高到低使用。默认情况下所有 swap 设备的优先级是负值(通常是 -2),系统基本是平均使用。你可以手动设置:

swapon -p 100 /swapfile1

优先级范围是 0 到 32767,数字越大越优先。扩容场景的用法就是给新的大 swap 一个高优先级,让它先被填满,旧 swap 哪怕不删,也只是个兜底。这个思路在线扩容时特别好用:你不需要急着清理旧空间。

swappiness 也顺便说一下。这个参数控制内核把内存页换到 swap 的激进程度,范围 0-100,默认通常是 60。服务器上我一般调成 10 左右,减少不必要的 swap 写入:

sysctl vm.swappiness=10 echo 'vm.swappiness=10' >> /etc/sysctl.conf

设置完不用重启,立即生效。

fstab 的坑前面已经说了两个(UUID 变化、nofail 选项),还有一个很多人在意的:swap 文件的 fstab 行如果写错,开机时会卡 90 秒甚至更久,卡在a start job is running for dev-disk-by...swap。解决方案除了 nofail,还可以在写 fstab 之前用findmnt或swapon -a提前验证。改完配置后重启前,一定先执行:

swapoff -a swapon -a

能顺利执行完,fstab 基本就没问题。

5. 现场问题排查速查表

把这些年遇到的 swap 扩容报错整理成一张速查表,基本覆盖了 90% 的翻车现场。

5.1 高频报错及原因分析

报错信息原因解决办法
swapon failed: Invalid argumentswap 文件所在的文件系统不支持(NFS、tmpfs 等)或使用了 fallocate 导致的 holes换 dd 重新创建,或改用本地文件系统
swapon: /swapfile: read swap header failedmkswap 没有成功执行先执行 mkswap 再 swapon
swapfile has holesfallocate 创建的文件在部分文件系统上不连续删除文件,改用 dd 重新创建
Permission deniedswap 文件权限过大,普通用户可读chmod 600
开机卡在 swap 等待fstab 中 swap 条目异常进入紧急模式修正 fstab,或加 nofail
lvextend后 free 看不到变化逻辑卷扩展了但 swap 区域没有重建swapoff 后 mkswap 再 swapon
mkswap报Device is busy该设备正在被内核用作 swap先 swapoff 再执行

这里我特别想强调的是第一行。NFS 上的文件做 swap 是直接不行的,swapon会明确报Invalid argument。之前有人问我能不能把 swap 放在云盘的 NFS 挂载目录下,我说别想了,swap 必须是本地块设备或本地文件系统上的文件。

5.2 几个生产环境里的冷门经验

第一,查询哪个进程在大量占用 swap,有一个快速办法:

for f in /proc/*/status; do awk '/VmSwap/{sw=$2} /Name/{n=$2} END{print sw, n}' $f; done | sort -rn | head -10

这条命令能列出占用 swap 最多的前 10 个进程。扩容之前看一眼这个,往往能发现有进程内存泄漏,光扩 swap 治标不治本。

第二,关于 swap 大小的老生常谈要纠正一下。“物理内存的 2 倍”这种说法是当年内存只有 512M 时代的经验,放到现在动辄 64G、128G 内存的服务器上完全不适用。我的习惯是:纯计算型服务器如果内存充足,swap 给 4G 到 8G 兜底就够;内存小(比如 4G 以下)的机器,swap 做成内存的 1 到 2 倍更稳。swap 不是越大越好,因为 swap 使用的磁盘写在性能和寿命上都有代价。

第三,云盘在线扩容有了新空间之后,如果你打算新建 swap 文件,记得先用df -h确认目标挂载点空间足够。很多人习惯在根目录/下建文件,结果根分区空间只剩 2G,还想建 8G 的 swap,大概率创建失败。遇到这种情况,把 swap 文件放到空间更大的数据盘上去,比如/data/swapfile,完全没问题,只要那个挂载点支持本地文件系统。

第四,容器环境里对 swap 的操作有个特殊点:如果你在容器里执行swapon --show看到的是宿主机信息,说明容器没权限管理自己的 swap。这种场景下不要白费力气,swap 配置应该在宿主机层面处理。

写在最后的体会

做过太多次 swap 扩容之后,我现在最深刻的感受是:扩容本身不复杂,复杂的是别把自己搞挂。在线扩容的思路总结下来其实就三条——优先新增代替修改、swapoff 前必须评估内存余量、fstab 配置永远加 nofail。这三条做到,基本不会翻车。另外我个人有个习惯,每次扩容完会顺手在/etc/sysctl.conf里检查一下 swappiness,避免系统没事儿就把内存往 swap 里倒。如果你现在的服务器 swap 已经在报警边缘,不妨按这篇文章的决策顺序来:先看形态,再选方案,动 swapoff 前三思,扩容完成立刻验证。整个过程冷静下来,十五分钟就能搞定。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 13:48:29

用Python生成器与itertools搭建内存友好的量子计算模拟器

这期是系列里第30篇,聊一个看起来硬核、实际思路却很朴素的组合:用Python的itertools生成器体系,去搭一个量子计算模拟器。很多人学量子计算时第一个念头就是“自己写个模拟器玩玩”,结果一动手就卡在同一个地方——n个量子比特的…

作者头像 李华
网站建设 2026/10/16 16:34:38

计算机网络五层模型考点与学习路线全解析:从教材到DevOps实践

1. 先把教材和学习路线定下来,再谈怎么学 1.1 谢希仁、王道、自顶向下、湖科大教书匠,到底该选哪一套 搜“计算机网络课程”的人,基本分成三类:准备408考研的、期末考前极限突击的、工作之后回来补网络基础的(尤其做D…

作者头像 李华
网站建设 2026/10/17 6:13:29

Django认证与权限:从用户模型到行级隔离的完整实践

这几年做 Django 项目,总能看到新人对着auth应用一头雾水:登录注册不是现成的吗?权限不也内置了吗?可真到了自己动手写一个带角色、带数据隔离的业务系统,才发现内置那套东西只是地基,上面该盖什么楼、怎么…

作者头像 李华
网站建设 2026/10/21 6:44:13

屏幕多播实战避坑指南:从pingmuguangbo.rar到稳定UDP多播链路

简介:本资源是一个基于C#开发的局域网屏幕多播与广播工具源码包,面向网络编程初学者、Windows桌面应用开发者及远程教学/协作场景的技术实践者,解决多终端同步接收屏幕图像的实际需求。压缩包共64个文件,含15个核心C#源码&#xf…

作者头像 李华
网站建设 2026/10/17 6:13:28

空输入处理与博文生成:从缺失内容到结构化创作的引导实践

抱歉,我收到的输入内容是空的:没有【项目标题】、【项目正文】、【关键词】或【摘要描述】。 我无法在没有实质内容的情况下凭空产出博文——那样写出来的东西会脱离你想表达的核心,反而对你的项目没有价值。 麻烦你补充以下信息&#xff1…

作者头像 李华