1. 为什么要用 swapoff:不只是“关掉交换分区”那么简单
如果你管理过 Linux 服务器,一定对 swap(交换分区)不陌生。内存不够用的时候,系统会把一部分不活跃的内存数据挪到磁盘上的 swap 空间,腾出物理内存给正在运行的程序。这个机制在物理内存捉襟见肘的老机器上是救命稻草,但在内存充裕、甚至内存已经成了性能瓶颈的现代服务器上,swap 有时候反而是帮倒忙。
我见过不少运维新手,看到服务器 load average 飙升、io wait 居高不下,第一反应是加内存、杀进程,很少有人会想到去检查 swap 的使用情况。实际上,很多所谓的“服务器卡顿”,罪魁祸首恰恰是 swap 在频繁读写——当系统把大量内存页换入换出时,磁盘 I/O 会被瞬间打满,应用响应自然就慢了。
swapoff 命令的作用,就是主动关闭 swap 空间。它存在的意义远不止“关掉一个功能”这么简单,常见的应用场景有这么几类:
- 内存回收调优:当你发现系统的 swap 使用率异常高,而物理内存明明还有富余时,可以把 swap 关掉再重新开启,清理掉那些被换出的缓存数据。
- 磁盘维护:比如你要缩小或删除一个 swap 分区、移动 swap 文件的位置,必须先 swapoff 才能操作。
- 性能调优:某些对延迟极其敏感的应用(比如数据库、消息队列),swap 的磁盘读写会带来不可接受的性能抖动,需要在运行时临时关闭 swap。
- 容器和虚拟化环境:在 Docker 或 Kubernetes 节点上,swap 的存在可能导致内存配额失效,很多生产环境会直接关掉 swap。
这篇文章我会从 swapoff 的基本用法讲起,结合我日常运维中踩过的坑,把关闭 swap 的完整实操流程、注意事项和排查技巧都梳理一遍。整个过程不复杂,但细节很多,稍有不慎就可能搞挂线上服务——尤其是当你对内存情况没有一个全局判断的时候。
无论是刚接触 Linux 的新手,还是已经有几年经验的运维,这篇都能给你一些参考。文中的操作我在 CentOS 7/8、Ubuntu 20.04/22.04、Debian 11 上都验证过,命令本身是通用的,系统差异主要体现在开机自启配置上,这个我会单独说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. swapoff 命令基础:语法、参数与工作原理
2.1 命令语法和参数全解
swapoff 的用法非常简洁,基本语法如下:
bash复制swapoff [选项] [设备或文件]
常用的选项就三个:
| 参数 | 作用 | 使用场景 |
|---|---|---|
-a |
关闭所有在 /etc/fstab 中标记为 swap 的设备 |
一键全关,最常用 |
-v |
显示详细执行信息 | 排错时确认正在处理哪个设备 |
--help |
查看帮助信息 | 记不清参数时随手查看 |
不带任何参数、直接指定设备名或文件路径的用法更精确,比如:
bash复制swapoff /dev/sda2
swapoff /swapfile
这里要注意,设备名不是随便写的。你必须先用 swapon --show 或 free -h 确认当前生效的 swap 到底是什么,再决定用哪个设备名或文件路径。
2.2 swapoff 背后发生了什么
理解 swapoff 的工作原理,有助于你预判操作的后果。当执行 swapoff 时,内核会尝试把存放在该 swap 空间中的所有内存页重新搬回物理内存(RAM)。这个过程是同步阻塞的,意味着在搬移完成之前,命令不会返回。
关键点在于:如果物理内存的可用空间不足以容纳 swap 中的全部数据,swapoff 就会失败,并给出类似 swapoff failed: Cannot allocate memory 的报错。这种情况在内存吃紧的机器上非常常见,后面我会专门讲怎么处理。
另外还有个容易被忽略的细节:swapoff 会把 swap 空间里的数据优先搬回物理内存,如果物理内存实在放不下,内核会把一部分数据换出到其他仍然开启的 swap 空间。也就是说,如果你有多个 swap 设备,只关其中一个,数据会“乾坤大挪移”到剩下的 swap 里,而不是直接写到磁盘上的普通文件系统。
2.3 swapon 与 swapoff 的配合
既然说了 swapoff,就不得不提它的孪生兄弟 swapon。这两个命令一个是开、一个是关,本身都不复杂,但配合使用能完成一些高级操作。
最典型的就是“重置 swap”——先 swapoff 再立即 swapon,效果是清空 swap 中的所有数据,让 swap 回到一个干净的状态。我通常在排查内存泄漏、或者感觉 swap 碎片化严重时这么操作,相当于给交换空间做了一次“碎片整理”。
关于 swapon 的用法,这里简单提一句语法就够用了:
bash复制swapon [选项] [设备或文件]
但本文的重点还是 swapoff,下面的实操环节,我会按照实际运维的完整流程来走一遍。
3. 实操前必读:关闭 swap 前的检查清单
在动手执行 swapoff 之前,有一个环节不能跳过去——那就是先搞清楚当前系统的内存和 swap 状况。很多线上事故,都是因为运维人员不看内存直接敲命令导致的。我把这一步叫做“关闭 swap 前的三查”,查清楚再动手,基本不会出岔子。
3.1 三查:内存、swap 用量、进程占用
第一查:物理内存和 swap 的整体情况
bash复制free -h
这是我最常用的命令,输出大概长这样:
text复制 total used free shared buff/cache available
Mem: 15Gi 8.2Gi 1.1Gi 245Mi 6.1Gi 6.4Gi
Swap: 2.0Gi 1.2Gi 817Mi - - -
重点关注 Swap 那一行的 used 和 free 列。如果 used 的值很大,却接近 total 的容量,就要特别小心了——因为关闭 swap 意味着要把这 1.2Gi 的数据塞回物理内存。看 Mem 行的 available 列,这个值表示在不触发额外 swap 的情况下,还能分配给新程序的内存。只有当 available 明显大于 swap used 时,才能安全关闭。
第二查:当前 swap 设备的具体信息
bash复制swapon --show
输出示例:
text复制NAME TYPE SIZE USED PRIO
/dev/sda3 partition 2G 1.2G -2
/swapfile file 512M 0B -3
这里能看到系统里有几个 swap 设备、各自用了多少。如果主要占用集中在其中一个设备上,而另一个基本是空的,可以考虑只关那个占用高的,保留空的应急。
第三查:Swap 使用率最高的进程(拓展)
bash复制for file in /proc/*/status ; do awk '/VmSwap/{swa+=$2} END {print swa}' "$file" 2>/dev/null; done | sort -n | tail -5
这个命令比较粗糙,更直观的方式是用 top 进入交互模式后按 O 再按 p 排序(按 swap 使用排序),或者用 htop 查看。实际上,找出谁在消耗 swap 能帮你判断:如果是一个明确可以重启的服务,直接重启它并释放内存,比强行 swapoff 更优雅。
3.2 判断能否安全关闭的量化标准
结合我的经验,这里给一个可量化的判断标准(不完全绝对,但很实用):
- 标准一:
Mem available≥Swap used+ 1GiB 余量。满足这个条件,关闭 swap 基本不会有太大风险。 - 标准二:swap 使用率低于总容量的 30%,且物理内存尚有 20% 以上空闲。这种情况关闭 swap,代价很小。
- 标准三:如果是业务低峰期执行(比如凌晨),即使内存略紧,也可以先尝试执行,失败了大不了再想办法。
如果你的系统连上述标准的一半都达不到,我建议先别急着 swapoff,优先考虑扩展物理内存、或者定位并杀掉内存大户进程。强行关闭 swap 导致的 OOM(内存溢出)杀进程,损失可比卡顿严重得多。
3.3 数据备份与回滚方案
关闭 swap 本身不涉及数据永久删除,但凡是动到系统配置的运维操作,我都建议你先想好“怎么回滚”。
如果你只是临时关闭 swap(比如为了完成某个调优测试),后续还要重新开启,那么回滚操作就是 swapon /dev/sda3,这个很简单。但如果你的目的是永久关闭 swap,那就必须提前备份 /etc/fstab:
bash复制cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S)
等操作全部完成、确认系统稳定运行一段时间后,再决定要不要删除这个备份文件。另外,如果你修改了内核参数 vm.swappiness(用来控制系统使用 swap 的倾向程度),也要记录下来原来的值,方便回退。修改内核参数的常用方式是:
bash复制sysctl vm.swappiness
vm.swappiness = 60
如果你为了优化性能把 swappiness 临时改成了 0,别忘了在关闭 swap 后确认是否需要持久化。不过这是另一个话题了,文章后面会简单提到。
4. 实战操作:不同场景下的 swapoff 完整步骤
4.1 场景一:临时关闭单个 swap 分区
这是最基础的操作。假设我们已经通过 swapon --show 确认了 swap 设备是 /dev/sda3,并且内存充足,直接执行:
bash复制sudo swapoff /dev/sda3
如果想确认执行结果,可以紧跟一条命令:
bash复制swapon --show
如果输出为空,说明所有 swap 都已关闭;如果仍然显示某个设备,说明那个设备还在生效。也可以看 free -h,Swap 行的总容量和已用变成 0,就代表关闭成功了。
注意,这种临时关闭的方式,在系统重启后会失效——因为 /etc/fstab 里的配置仍然存在,开机时系统会重新挂载 swap。
4.2 场景二:临时关闭所有 swap
当你有多个 swap 设备/文件时,一个个关太费劲,用 -a 参数一把梭:
bash复制sudo swapoff -a
这个命令会读取 /etc/fstab 中所有标注为 swap 的条目,并依次关闭。它的输出是静默的,成功与否需要自己验证。我建议执行完立刻运行 free -h 确认。
我在生产环境用了很多次 swapoff -a,整体很稳定。但有一个场景要特别留意:如果某一块 swap 设备出现了 IO 错误或者处于异常状态,-a 可能会在中途停下来。这时候加上 -v 参数重试,能看清楚卡在哪个设备上。
4.3 场景三:永久关闭 swap(并禁止开机自启)
永久关闭 swap 是我在配置 Kubernetes 节点、数据库服务器时最常做的操作。步骤分三层,层层递进。
第一步:临时关闭正在使用的 swap
bash复制sudo swapoff -a
第二步:注释掉 /etc/fstab 中的 swap 条目
用编辑器打开 /etc/fstab,找到类似下面这样的行:
text复制/dev/sda3 none swap defaults 0 0
或者:
text复制/swapfile none swap defaults 0 0
在这一行的行首加上 # 注释掉,保存退出。注意,/etc/fstab 的语法非常严格,注释一定要在行首,行内别乱加空格。修改后建议用以下命令验证语法是否有误:
bash复制sudo mount -a
这个命令会重新挂载 /etc/fstab 中的所有文件系统。如果没报错,说明 fstab 语法没问题;如果报错,马上检查你刚才的修改,改回原样。
第三步:确认永久关闭生效
重启系统后再次运行:
bash复制sudo swapon --show
如果输出为空,说明 swap 已经彻底禁用,开机也不会再自动挂载。
4.4 场景四:调整 swap 容量时使用 swapoff
举个实际例子。我之前遇到一台服务器,最初安装系统时 swap 分区只分了 2GB,后来跑了个内存密集型的分析任务,swap 明显不够用,频繁把磁盘 I/O 打满。我的处理思路是:扩大 swap 容量。
扩大 swap 有两种思路,一种是直接调整分区大小(需要操作磁盘分区表,风险较高),另一种是新增一个 swap 文件,比动分区更安全、更灵活。具体操作如下:
先关掉原来的 swap:
bash复制sudo swapoff /dev/sda3
然后创建新的 swap 文件,比如 4GB:
bash复制sudo fallocate -l 4G /swapfile # 或者用 sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
再把旧的 swap 分区从 /etc/fstab 中移除,把新的 swap 文件写入 /etc/fstab:
text复制/swapfile none swap defaults 0 0
这样系统重启后就会优先使用 4GB 的 swap 文件,旧的 2GB 分区就退役了。这种方案的好处是,swap 文件可以放在数据盘上,不受系统盘分区大小的限制,扩容缩容都方便。
这里要特别强调一下:fallocate 命令创建的文件在某些文件系统(比如 ext4)上可能会出现问题,如果你在 swapon 时报错 swapon: /swapfile: swapon failed: Invalid argument,可以改用 dd 命令重新创建,这是已知坑,踩过的人不少。
4.5 场景五:忽略正在使用的 swap 分区的特殊参数
实际生产环境中,某些 Linux 发行版(比如 RHEL/CentOS 7+)在 /etc/fstab 里的 swap 条目可能是这样的:
text复制/dev/mapper/centos-swap swap swap defaults 0 0
其中 swap 字段出现了两次,第一次表示挂载点,第二次表示文件系统类型。这种格式在 swapoff 时完全不影响,swapoff -a 仍然可以正常关闭。
但如果你的 swap 配置了 pri 参数(优先级),比如:
text复制/dev/sda3 none swap defaults,pri=5 0 0
执行 swapoff 后,优先级配置也会一并清除,再次 swapon 时如果没有重新指定,会采用默认优先级。这也是为什么有些系统管理员在动态调整 swap 优先级时,会频繁用 swapoff + swapon 组合的原因。
5. 常见问题与排查技巧实录
5.1 报错:Cannot allocate memory
这是 swapoff 最经典的报错,完整提示是:
text复制swapoff: /dev/sda3: swapoff failed: Cannot allocate memory
意思很简单:物理内存不够,放不下 swap 里的全部内容。处理优先级从高到低,我给出三种解法:
解法一:清缓存(临时腾出内存)
bash复制sudo sync && echo 3 > /proc/sys/vm/drop_caches
这会把页缓存(page cache)、目录项缓存(dentries)和 inode 缓存全部清掉,通常能释放出几个 GB 的内存。注意,这个操作对正在运行的进程没有影响,只是清空磁盘缓存,代价是下次读取文件时会稍微慢一点。
解法二:找出内存大户,杀掉或重启
前面提到的 for file in /proc/*/status 扫描法,这次派上用场。如果发现某个应用(比如 Java 进程、Chrome 浏览器)占用了大量 swap,可以优雅地重启它,或者直接 kill 掉。对于无法重启的数据库进程,可以考虑在业务低峰期操作。
解法三:分批关闭多个 swap 设备
如果你有多个 swap 设备,且总量特别大,一次全关肯定内存爆炸。这时候可以分批操作:
bash复制sudo swapoff /dev/sda3
sudo swapoff /dev/sdb2
先关小的,让数据慢慢搬回内存,过一会再看内存状态,再关下一个。这种“挤牙膏”式的关闭方式,虽然慢,但稳。
5.2 报错:Invalid argument
text复制swapon: /swapfile: swapon failed: Invalid argument
这个报错多出现在使用 fallocate 创建 swap 文件之后。原因在于 fallocate 在部分文件系统上会分配带空洞的文件,swap 文件不支持这种特性。解决办法是用 dd 重新生成:
bash复制sudo rm -f /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
我每次创建 swap 文件,现在已经默认直接用 dd,省得踩这个坑。
5.3 关闭后系统变得异常卡顿
有时候明明 swapoff 成功了,free 也显示内存够用,但系统反而变慢了。这大概率是因为 swapoff 的过程触发了大量内存页搬移,而搬移操作需要频繁读取磁盘上的 swap 数据,磁盘 I/O 在这段时间内处于高负载状态。
遇到这种情况不用慌,等待几分钟让系统稳定下来。如果持续卡顿,检查是不是有哪个进程在 swapoff 前被换出了大量内存,现在回去读盘导致 I/O 瓶颈。这种场景下,iostat -x 1 能帮你快速定位。
5.4 开机后 swap 又自动出现了
如果你明明执行了 swapoff -a,重启后 swap 又存在了,十有八九是 /etc/fstab 里的条目没有注释掉。解决方案前面已经说过了,这里再补充一个细节:有些云主机的初始化脚本(cloud-init)可能会在启动时自动创建并启用 swap,跟 fstab 无关。
在云服务器上遇到这种情况,需要检查以下位置:
bash复制cat /etc/cloud/cloud.cfg | grep -i swap
或者查看 /etc/systemd/system 下面有没有 swap 相关的服务:
bash复制systemctl list-unit-files | grep swap
如果确认是 cloud-init 造成的,可以在 /etc/cloud/cloud.cfg 里禁用 swap 相关的模块,具体配置因云厂商而异,这里就不展开了。
5.5 现场排查速查表
| 现象 | 可能原因 | 快速定位命令 | 解决方向 |
|---|---|---|---|
| swapoff 报 Cannot allocate memory | 物理内存不足 | free -h、ps aux --sort=-%mem |
清缓存、杀进程、分批关 |
| swapoff 卡住不动 | swap 数据量大、磁盘 IO 慢 | iostat -x 1、iotop |
耐心等待,或先加大磁盘 IO 能力 |
| swapoff 后系统 OOM | 误判内存余量 | dmesg -T | grep -i oom |
立即重启关键服务,下次先加内存 |
| 永久关闭失败 | fstab 没注释 | cat /etc/fstab |
注释掉 swap 行 |
| 云主机重启后 swap 恢复 | cloud-init 自动配置 | systemctl list-unit-files | grep swap |
检查并禁用相关配置/服务 |
| swapon 新文件失败 | fallocate 空洞文件 | ls -ls /swapfile |
改用 dd 创建 |
6. 经验分享:这些操作细节值得你反复默读
6.1 swapoff 的最佳执行时机
我个人的经验是:凡是涉及生产环境的 swapoff,一定选择业务低峰期,并且要提前通知相关方。原因很简单,swapoff 是一个确定性很高的操作,但在内存和磁盘 I/O 紧张时,它可能在短时间内显著影响系统性能。你不想在用户访问高峰期看到数据库响应超时吧。
当然,有些紧急情况(比如内存泄漏导致系统濒临 OOM)容不得你挑时间,这时候只能权衡。如果必须立刻执行,建议先清缓存、再分批关闭,把风险降到最低。
6.2 在容器平台上的特殊考量
使用 Docker 或 Kubernetes 时,swapoff 需要额外注意。Docker 的默认行为是容器共享宿主机的 swap 设置,如果你在宿主机层面永久关闭了 swap,容器内部的 free 看到的 swap 也会消失。这对某些依赖 swap 的容器镜像是个隐性问题——比如某些 Java 应用启动时,JVM 默认会按系统内存的一定比例预留堆内存,如果 swap 消失导致可用内存评估产生偏差,可能引发 OOM。
在 Kubernetes 节点上,很多发行版的 kubelet 配置了 --fail-swap-on=true,这会导致节点上有 swap 时 kubelet 拒绝启动。所以如果你在 K8s 节点上部署,不仅要关闭 swap,还要确认 kubelet 参数与实际情况匹配。这里涉及的内容比较多,有兴趣可以另开一篇详细讲。
6.3 swapoff 不等于删除 swap
最后再强调一个概念性的问题:swapoff 只是把 swap 从内核的交换机制中摘除,并不删除交换分区或交换文件。这意味着你随时可以用 swapon 把它重新挂回来,数据和文件系统都还在。真的想删除 swap 文件,得用 rm 命令手动移除;想删除 swap 分区,需要用 fdisk 或 parted 修改分区表——那是另一个高风险操作了。
动手前分清“关闭”和“删除”的区别,能避免不少误操作。比如有些新手把交换文件给 rm 了,然后 swapoff 发现报错,就是因为文件已经没了,系统却还在使用它的 inode 维护 swap 空间。遇到这种情况,要么重新建立文件,要么启动 vm.swappiness 参数调整,让系统慢慢把数据搬回内存后再关闭。
6.4 补充:swap 与 swappiness 参数的联动
实际操作中很多人会发现,即使 swap 已经释放,系统还是偶尔会出现内存不足的报错。这可能跟 vm.swappiness 参数有关。这个参数控制内核有多“积极”地使用 swap,取值范围 0-100,默认通常是 60。数值越高,内核越倾向于把不常用的内存页换到 swap 上;越低则越倾向于保留在物理内存。
如果你在生产环境永久关闭了 swap,建议把 swappiness 调低(比如 10),这样即使重新开启 swap,系统也不会轻易把进程内存换出到磁盘。修改方式:
bash复制echo 10 > /proc/sys/vm/swappiness
持久化写入 /etc/sysctl.conf:
text复制vm.swappiness = 10
然后执行 sysctl -p 生效。这个参数放在 swapoff 附近一起调,能让内存管理更符合你的预期。
7. 写在最后:swapoff 只是磁盘维护的一把钥匙
熟悉 swapoff 之后,你会发现它其实是理解 Linux 内存与存储关系的一个绝佳切入点。通过一次 swapoff,你能直观地感受到物理内存、交换空间、磁盘存储这三者之间是如何动态协作的。这个认知,比单纯背命令参数有价值得多。
对我个人而言,swapoff 是服务器性能调优工具箱里一个不起眼但非常好用的工具。它不花哨,但关键时刻能解决大问题。希望这篇实操指南能帮你在使用它的时候少走弯路。如果你在实际操作中遇到了别的问题,欢迎留言交流——我踩过的坑也不少,咱们互相补补课。
