前几天一台线上服务器内存告警,我接到工单后登录机器,free -h 一看就发现问题了:Swap 分区只有 2G,used 已经到 1.7G,而物理内存还有 6G 空闲。很明显是规划不合理,加上默认的 swappiness 策略太积极,导致内核把大量冷页面丢到了 swap 里。当时要做的操作很常规——把 swap 从 2G 扩到 8G,但前提是得先把旧的 swap 关掉。我本来以为 swapoff 一条命令几秒钟搞定,结果命令敲下去卡了十几分钟,期间系统负载飙得老高,差点把线上服务拖垮。也是从那次之后,我才认真把 swapoff 这个“看上去很简单”的命令研究了一遍。
这篇是 Linux 命令大全系列的第 8 篇,主题就是磁盘维护里的 swapoff 命令。我会把 swapoff 是什么、什么时候用、怎么用、常见报错怎么解决,以及我在生产环境里踩过的坑一次性讲清楚。适合刚接触 Linux 运维的读者建立概念,也适合有经验的工程师在做 swap 扩容、开关、迁移时直接对照参考。文章涉及的核心关键词是 Linux、磁盘维护、swapoff 命令,以及与之配套的内存管理参数。
1. swapoff 是什么:先搞懂这个命令在关哪块内存
1.1 从内存页的角度理解 Swap 和 Swapoff
很多教程喜欢直接把 swap 翻译成“虚拟内存”,叫法没错,但容易产生误导。更准确的说法是:swap 是一块磁盘上的交换空间,当物理内存不够时,内核会把一部分暂时用不到的内存页写到磁盘里,腾出物理内存给更活跃的页面使用。整个系统看起来内存变“大”了,但实际上是用磁盘速度换内存空间。
swapoff 做的事正好相反。它会让内核停止使用某个交换空间,并且把这个交换空间里已经存放的内存页“搬回”物理内存。注意,这里是需要真的把数据搬回内存的,不是像关闭一个文件那样把它丢弃就行。所以 swapoff 能否成功,根本上取决于一件事——当前物理内存是否还有足够余量来容纳 swap 里的数据。
这也能解释我开头遇到的情况:虽然 free 显示还剩 6G 物理内存,但当时内存分配比较零散,再加上系统里有不少文件缓存,内核在换入换出的过程中触发了大量的回收动作,导致 swapoff 迟迟无法完成。所以,swapoff 看似是个磁盘维护命令,实际上和内存管理、页面回收策略深度绑定。
1.2 什么时候真正需要用到 swapoff
swapoff 最常见的几个使用场景如下。
调整 swap 大小:这个最典型。服务器初始规划的 swap 太小或太大,需要扩容量或缩减,就要先 swapoff 旧设备或旧文件,再重新 swapon 新的。
迁移 swap 位置:比如想把 swap 从机械盘挪到 SSD,或者从磁盘分区迁到裸设备,甚至在某些场景下改用 zram / zswap,都需要先把旧的关掉。
排查内存问题:怀疑某些进程异常消耗 swap 时,可以临时 swapoff,观察系统行为,确认问题出在哪个进程。
满足特定运行环境要求:部分分布式集群、容器平台在初始化时会要求关闭 swap,比如部署 Kubernetes 节点时,很多场景下官方建议把 swap 关掉,避免调度器对内存的判断出现误差。
销毁或重做磁盘分区:当你需要对一块磁盘重新分区、格式化时,如果该分区正在被用作 swap,系统会提示设备忙,必须先用 swapoff 释放占用。
1.3 swapoff 对系统的影响范围
swapoff 的影响范围其实比命令本身看起来大很多。首先,它直接影响内存子系统,触发页面换入操作;其次,它会影响所有使用 swap 的进程,因为这些进程的虚拟内存可能有一部分在 swap 里,swapoff 时要逐页归还;再次,在高内存压力情况下,swapoff 可能触发 OOM killer,系统会开始杀进程来释放内存,这是生产环境最需要注意的后果。
所以,我一般在操作之前都会提醒自己:swapoff 不是一个可以毫无负担执行的命令,它背后牵连的是内存、磁盘 I/O、CPU 和进程调度。看清当前状态再动手,是对线上服务的基本尊重。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. swapoff 的参数并不复杂,真正复杂的是时机选择
2.1 参数表:其实只有两三个真正常用的选项
swapoff 的语法很简洁:
bash复制swapoff [选项] [设备或文件]
我整理了一个参数表,方便你随时查:
| 参数 | 作用 | 实际使用注意 |
|---|---|---|
-a / --all |
关闭 /proc/swaps 中记录的所有交换空间 |
一次全关,生产环境慎用,最好明确指定设备 |
-v / --verbose |
显示详细执行过程 | 能看到每个交换空间的关闭状态,排查问题好用 |
-e / --ifexists |
跳过不存在的交换设备,静默忽略错误 | util-linux 2.36 以后才支持,老版本没有 |
不带任何参数时,swapoff 后面必须跟具体的交换分区或 swap 文件路径,比如 swapoff /swapfile 或 swapoff /dev/sda5。要注意的是,这个参数不是让你随便填的,填写的路径必须已经在 /proc/swaps 里处于启用状态,否则会提示找不到设备。
2.2 执行前先看清当前 swap 的状态
我几乎不在没看状态的情况下直接执行 swapoff。判断当前 swap 情况,有三条命令足够:
bash复制free -h
swapon --show
cat /proc/swaps
free -h 用来快速查看 swap 总量和使用量;swapon --show 输出更规范,包含设备名、类型、大小和优先级;cat /proc/swaps 是最底层的视图,和 swapon 的结果基本一致。如果 swap 的 used 数值很大,而 free 显示的物理内存 available 又不够,那我就会先想办法腾出内存,而不是硬跑 swapoff。
举一个实际判断的例子:假设输出如下。
bash复制$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 2G 1.8G -2
$ free -h
total used free shared buff/cache available
Mem: 31Gi 12Gi 6.0Gi 1.2Gi 13Gi 17Gi
Swap: 2.0Gi 1.8Gi 210Mi
这台机器 available 还有 17G,swap 里只有 1.8G,理论上 swapoff 可以成功。但如果 available 只有 1.5G,swap 里却有 2G 数据,那 swapoff 大概率会失败或卡死。这个对照逻辑是判断能否安全执行的核心。
2.3 三种典型调用方式与适用场景
第一种是关闭单个指定交换空间:
bash复制sudo swapoff /swapfile
适用于明确知道要关哪一个的时候,比如扩容 swapfile 之前。
第二种是关闭所有交换空间:
bash复制sudo swapoff -a
适用于系统初始化脚本、临时清理所有 swap 的场景。但我不建议在业务高峰期直接对生产服务器执行,因为它会一次性把所有 swap 页面全部换回内存,瞬时 I/O 压力非常大。
第三种是加 -v 观察过程:
bash复制sudo swapoff -v /dev/sda5
关闭时会输出具体的执行状态,比如 swapoff 开始、swapoff 成功等。如果命令卡住,-v 至少能让你判断它卡在哪一步。我在排查问题时经常用这种方式,至少比干等强。
3. 实操:完整完成一次 swap 扩容并安全关闭旧 swap
3.1 案例背景:给 2G swap 扩容到 8G
最经典的实操场景就是把 swap 从 2G 扩到 8G。这里我以 swapfile 方式为例,因为现在很多云服务器默认就是 swapfile,而不是独立分区。
第一步,确认当前状态:
bash复制swapon --show
free -h
df -h /
第三行是为了确认根目录磁盘空间是否足够放新的 swap 文件。8G 的 swapfile 会占用根分区 8G 空间,如果磁盘不够就要另想办法,比如放到数据盘或者调整计划。
第二步,调整 swappiness 降低换入压力:
bash复制sudo sysctl vm.swappiness=10
为什么要先调这个参数?因为默认的 swappiness 往往偏高,内核换页比较积极。直接 swapoff 时,大量页面要一次性换入物理内存,如果不先降低内核继续分配新页面的意愿,很可能边换入边换出,形成抖动,让 swapoff 变慢。调低后,至少能让内核在换入期间克制一些。
第三步,执行关闭命令:
bash复制sudo swapoff -v /swapfile
这一步就是最容易卡住的地方。执行后观察 free -h,你会发现 swap used 在一点点下降,物理内存被慢慢占用,等 swap used 变成 0,命令就结束了。如果十几分钟还没有归零,需要按第 4 节的排查方法处理。
第四步,删除旧的 swap 文件并重建:
bash复制sudo rm -f /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1M count=8192
sudo chmod 600 /swapfile
sudo mkswap /swapfile
注意几个细节:chmod 600 是必须的,否则 mkswap 会警告文件权限不安全;创建文件用 dd 而不是直接 fallocate,原因后面展开。
第五步,写入 /etc/fstab 持久化配置:
bash复制/swapfile none swap sw 0 0
如果你的发行版使用 systemd 来管理 swap 设备,还需要检查一下是否有对应的 .swap unit 文件残留。常见做法是用 systemctl list-units --type=swap 查看,如果有旧的 swap unit,直接 systemctl disable 掉,否则重启后系统可能会按旧配置重新挂载 swap。
第六步,启用并验证:
bash复制sudo swapon /swapfile
swapon --show
free -h
到这里,swap 扩容流程就走完了。整个过程中最核心、最容易出问题的就是第三步 swapoff,其余的步骤算是常规磁盘操作。
3.2 如果是 swap 分区,该怎么办
如果系统用的是独立 swap 分区,流程略有不同。swapoff /dev/sda5 之后,你还要处理分区表:用 fdisk 或 gdisk 删除旧分区、新建分区,再 mkswap、swapon。操作分区表有风险,一定要提前备份分区信息,最好离线操作或者请有经验的人把关。我个人更倾向直接加一块 SSD 专门做 swap 分区,避免动系统盘分区表,毕竟分区表一旦出错,整个系统都可能起不来。
3.3 systemd 环境下的隐藏坑
在 systemd 为主的发行版上,光修改 /etc/fstab 往往不够。有些系统会生成 /etc/systemd/system/swapfile.swap 之类的 unit 文件,里面自带 What=/swapfile 配置。如果你只是 swapoff 再删除文件,却忘了禁用这个 unit,下次开机时系统会自动创建空的 swap 文件或者反复报错。正确的做法是,先检查:
bash复制systemctl list-units --type=swap
systemctl list-unit-files --type=swap
发现有不需要的 swap unit,就执行:
bash复制sudo systemctl disable swapfile.swap
sudo rm /etc/systemd/system/swapfile.swap
sudo systemctl daemon-reload
这个坑很隐蔽,第一次遇到时我折腾了挺久,后来养成习惯:凡是涉及 swap 开关的操作,fstab 和 systemd 两边都会检查一遍。
4. swapoff 常见报错与排查技巧:哪些坑我替你踩过
4.1 “Cannot allocate memory”的三种破局思路
swapoff 最常见的报错就是:
bash复制swapoff: /swapfile: swapoff failed: Cannot allocate memory
这个错误非常直白:swap 里的数据想要搬回物理内存,但内核分配不到足够的内存页。很多人的第一反应是“我明明 free 显示还有内存啊”,就像我开头遇到的情况一样。但请你注意,free 显示的 free/available 只是全局视角,内核在特定内存区域可能没有可用的连续页面,或者被其他机制占用了。
破局思路第一招:杀掉或暂停大内存进程。通过 top 按内存排序,找出占用最多的进程,结合业务情况做处理。如果是数据库之类的关键进程,不能乱杀,至少可以停掉一些不太重要的应用,腾出内存。
破局思路第二招:清缓存但不建议硬清。网上常说的 echo 3 > /proc/sys/vm/drop_caches 可以释放页缓存,但有风险,在繁忙的生产库上执行可能导致性能剧烈波动。我一般不用,除非是测试环境。
破局思路第三招:调整 swappiness 后重试。先把 vm.swappiness 临时调低,比如设到 1,等系统稳定一会儿,再执行 swapoff。这个思路是给内核降低继续换出的意愿,让物理内存页更多被保留给正在换入的页面。实测在很多场景下有效。
4.2 命令卡住不动,先查谁在占用 swap
如果 swapoff 执行了很久都没有返回,不要反复 Ctrl+C 再去试,那会加重系统负担。正确的做法是打开另一个终端,先看 free -h 里 swap used 的变化趋势,再看系统整体负载。如果 swap used 确实在下降,那只是时间问题;如果完全不动,说明有进程持续分配内存,导致换入换出僵持。
这时候可以找出到底谁占着 swap:
bash复制for pid in /proc/[0-9]*; do
if grep -q VmSwap "$pid/status" 2>/dev/null; then
echo "$pid $(grep VmSwap "$pid/status" 2>/dev/null)"
fi
done | sort -k3 -n -r | head -20
这条命令会列出占用 swap 最多的 20 个进程,输出格式类似:
text复制/proc/1234 VmSwap: 512000 kB
/proc/5678 VmSwap: 256000 kB
看到结果后,再结合业务判断是等待它自然释放,还是主动重启该服务。这个思路比盲目重试 swapoff 高效得多。
4.3 生产环境执行 swapoff 的时机与顺序
我个人的经验是,执行 swapoff 之前必须回答三个问题:现在是不是业务低峰期?这台机器有没有足够的 available 内存?有没有备用登录会话?
生产环境中,我不建议直接在业务请求很密集的时候执行 swapoff。操作前最好开启一个 tmux 或 screen 会话,防止 SSH 断线导致命令在终端关闭后中断,进而留下不可控的状态。操作命令也建议放在低峰期执行,比如凌晨,或者至少错开数据库备份、定时任务运行的时间段。
顺序上,我习惯这样做:
free -h、top、swapon --show三连看。- 调低 swappiness,等 10 到 30 秒。
- 用
swapoff -v指定具体设备执行,而不是-a。 - 另开终端监控
free -h和vmstat 1的输出。 - swap used 归零后再进行后续的删除、重建或分区操作。
这几步看起来繁琐,但每一步都在降低风险。真实踩过一次坑之后,你就会明白,多花两分钟做检查和监控,远比自己一直在工单里来回折腾要舒服。
5. 内存管理与磁盘维护:swapoff 前后的调优配合
5.1 vm.swappiness 参数:决定内核换页的积极程度
提到 swap 就绕不开 vm.swappiness。这个参数取值范围在 0 到 200 之间,默认值通常是 60。数值越大,内核越倾向于把不常用的内存页换到 swap;数值越小,越倾向于保留在物理内存中。
很多人以为把 swappiness 调成 0 就等于完全禁用 swap,其实不完全对。在较新的内核里,swappiness 为 0 只代表内核尽量不主动换出匿名页,并不表示绝对不使用 swap。如果真的希望系统几乎不用 swap,更稳妥的做法是同时调低 swappiness 并配合监控手工处理,而不是只依赖一个参数。
在生产环境中,我发现很多云服务器默认的 swap 策略比较激进,导致内存明明够用,swap 却已经用了不少。这时候可以考虑把 swappiness 从 60 降到 10 左右,能明显减少不必要的换页。但也要注意,如果调得太低,在突发内存压力下,系统可能没有足够的缓冲,直接触发 OOM。调参的核心思想是给系统留一点安全垫,同时减少无意义的磁盘写操作。
5.2 执行 swapoff 前后如何配合调整系统参数
在关闭 swap 前,我通常会先把 swappiness 临时调低:
bash复制sudo sysctl vm.swappiness=10
这么做是为了减少 swapoff 期间内核继续往其他 swap 空间写入新页面的可能。如果系统有多个 swap 设备,swapoff 会逐个处理,调低 swappiness 能避免旧数据还没换完,新数据又来了。
在关闭完成后,如果项目要求保持较低 swap 使用率,就把 swappiness 永久写入配置:
bash复制echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.conf
sudo sysctl --system
这里要注意,不同发行版对 sysctl 配置文件的加载顺序有差异,但 /etc/sysctl.d/ 目录下的配置一般都会被读取,文件名前面的数字决定了加载优先级,99 表示比较靠后加载,可以覆盖默认值。
5.3 顺便聊聊 zram 和 zswap
做磁盘维护时经常有人问,swap 到底放磁盘还是放压缩内存里更好。zram 是把一块内存压缩后当作 swap 设备,zswap 则是先压缩缓存,再决定是否写回后端磁盘。这两种方案在嵌入式或特定服务器场景下很有价值,但并不是默认标准配置。
如果你所在的系统对 I/O 延迟特别敏感,可以考虑 zram 替代传统磁盘 swap,因为压缩内存的读写速度远高于磁盘。但要注意,zram 本身依然占内存,实际可用的物理内存会减少,所以它适合内存资源相对宽裕的场景,不适合内存本来就紧张的小机器。这块内容展开讲篇幅很大,这里先点到为止,后续有机会再单独写一篇对比。
6. 几个我在生产环境总结出来的 swapoff 细节
6.1 创建新 swapfile 尽量用 dd,而不是 fallocate
现在很多教程推荐用 fallocate 快速创建 swap 文件,因为速度确实快。但我实测下来,在某些文件系统和内核版本上,fallocate 创建的文件在被 mkswap 和 swapon 使用时会出问题,尤其是支持文件空洞的 ext4 和 xfs。内核在交换文件上需要保证物理块已经真正分配,fallocate 创建的带空洞文件可能导致 swapon 失败。
所以我在生产环境创建 swapfile 时依然坚持用 dd:
bash复制sudo dd if=/dev/zero of=/swapfile bs=1M count=8192
虽然创建时间会长一些,但换来的是后续 swapon 的稳定可靠。这个细节可能不常被提到,但对做磁盘维护的运维来说非常实用。
6.2 swapoff 完成后别忘验证 fstab 和重启行为
swapoff 本身只是临时关闭,如果在 /etc/fstab 或 systemd unit 里还有对应配置,机器重启后又会自动启用。所以完整流程一定要包含持久化配置的修改和验证。
验证方法很简单,先看配置:
bash复制grep -i swap /etc/fstab
再看 systemd 状态:
bash复制systemctl list-units --type=swap --all
确保没有残留配置。如果改了 fstab,可以用 mount -a 先检测一遍语法,虽然它不会直接影响 swap,但能提前发现配置错误。谨慎一点,总没错。
6.3 经验之谈:错峰执行,挂 tmux,盯 vmstat
最后分享一条我自己的习惯。所有涉及 swapoff 的操作,我都会在 tmux 会话里执行,防止 SSH 断线导致任务状态不可控。执行过程中,另开一个窗口跑:
bash复制vmstat 1
重点观察 si 和 so 两列,也就是 swap in 和 swap out。正常情况下,swapoff 期间 si 会明显上升,因为数据在搬回内存。如果 so 也持续上升,说明系统还在继续换出,这就不太健康,需要确认是不是 swappiness 太高或者有其他进程在大量申请内存。
确认 swap used 归零后,我会再盯几分钟,等 si、so 都接近 0,才把机器重新放回业务流量。这套流程帮我避开了好几次潜在风险,也让我在操作 swap 相关命令时心里有底。希望这篇关于 swapoff 命令的实战解读,也能让你以后做磁盘维护时少踩几个坑。
