直接敲swapoff命令把交换分区关掉,这件事看起来简单,但在生产环境里翻过车的人才知道,这一条命令背后藏着好几个能让你大半夜爬起来处理的坑。我在运维Linux服务器的几年时间里,因为swap问题踩过的坑不少,从内存泄漏导致swap耗尽,到误关swap直接引发服务响应飙升,再到调整swap大小之后重启失效,这些场景我都经历过。所以这篇实操篇不打算只丢给你一个命令语法表格,而是想结合实际使用场景,把swapoff这个命令背后的原理、适用前提、完整操作链路以及失败时的排查方法一次性讲清楚,尤其是那些常规文档里不会告诉你的细节。无论你是准备Linux面试、接手一台swap占用很高的服务器,还是想在测试环境里腾出磁盘空间,这篇文章都值得你花十五分钟读完。
1. 为什么你必须理解swapoff在做什么,而不是只会敲一行命令
很多人把swapoff当成一个简单的开关命令,实际上它在系统里触发的事件链比表面上复杂得多。如果没搞清楚它到底在做什么就贸然执行,特别是内存资源紧张的时候,很容易让系统进入不可控状态。
1.1 swap到底在系统里扮演什么角色
swap这个概念来自早期物理内存很贵的年代,操作系统把一部分磁盘空间划出来当作内存的“溢出区”。当物理内存(RAM)不够用时,内核会把一些不常访问的内存页暂时写到磁盘的swap区域,腾出物理内存给活跃进程使用。内存页在swap区和物理内存之间来回迁移的机制,叫做页面交换。
用一个生活化的例子:swap相当于你桌子上堆满了文件之后,临时在旁边放了一个抽屉。桌子放不下的东西先塞进抽屉,等要用的时候再从抽屉里拿出来。抽屉好用,但频率太高就麻烦了,因为每次存取抽屉都要起身,比直接在桌面上拿文件慢得多。对应到系统里就是:swap用太多、交换太频繁,磁盘IO会成为瓶颈,整个系统的卡顿感会非常明显。
1.2 什么情况下才真的需要关闭swap
我遇到的场景大致可以分成三类。
第一类是数据库类的服务器,典型如MySQL、Redis、Elasticsearch。这类应用极度依赖内存访问速度,一旦内存页被换到swap,查询延迟会瞬间增高几个数量级。很多数据库官方文档都建议把swappiness调到很低甚至关掉swap,就是为了避免内核把关键数据页换到磁盘上。
第二类是内存充足的服务器。如果你的机器物理内存是64G,日常使用也就30G,那swap几乎常年是0的使用率。这种情况下保留swap反而意义不大,关闭它还省去了swap分区维护的麻烦,磁盘空间也能腾出来做别的事情。
第三类是容器和虚拟化宿主机或者嵌入式设备。Docker、Kubernetes这类容器平台在内存配额管理上对swap的介入很深,某些场景下swap的存在反而会干扰容器内存限制的判断。嵌入式设备大多用flash存储,swap频繁读写会加速flash磨损,这类设备上关闭swap几乎是标配。
注意一个很关键的判断:内存本来就紧张、每天都在swap边缘反复试探的机器,不要关swap。那不是优化,是拔掉救命稻草。所以我个人对关闭swap的建议永远是先看内存余量,再看业务类型,最后才动手操作。
1.3 内核执行swapoff时到底在干什么
swapoff执行时,内核要做的是把swap设备上存放的所有内存页读回来,重新放回物理内存。注意这里的措辞——是强制读回,不是按需读取。由于必须把所有这些页都装进RAM,所以这个操作天然就要求系统有足够的空闲物理内存,要大于或等于当前swap已使用的量。
如果可用物理内存不够,内核会尝试通过回收page cache(文件缓存)来腾地方。但如果连page cache回收光了都不够,操作就会直接失败,系统并不会“硬来”。理解了这一点,你就能明白为什么网上很多帖子说“内存不足的时候执行swapoff会报错”。实际上真实失败的报错信息是多变的,有的环境直接提示内存分配失败,有的则命令卡住不动,这些都指向同一个问题:可用内存不够。
所以swapoff这个操作最关键的前置检查,不是看命令语法,而是确认闲置物理内存足够承载swap里已经存下的数据。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前先看这三项:现状、用量、剩余内存
这部分我梳理了一套标准化的检查流程,每一步都对应着实际要解决的问题。很多新手一上来直接swapoff,等到系统提示失败才回来查内存,这时候往往已经浪费了不少时间。
2.1 free -m 怎么看内存和swap的余量
执行swapoff之前,我习惯先看一遍内存现状:
bash复制free -m
输出类似这样:
text复制 total used free shared buff/cache available
Mem: 32108 18028 3718 612 10362 12608
Swap: 16384 6072 0
这里要注意的是最后一行Swap的used值,这代表swap里已经存了多少数据。再看Mem行的available值,这是系统实际可以分配给新需求的可用内存(含可回收的缓存)。判断能不能安全执行swapoff,粗算就是available是否大于Swap的used。上面这个例子里,available约12.6G,swap used约6G,空间充裕,可以放心操作。
如果available比swap used还低,建议先不要关,先处理内存使用率的问题,要么清理缓存,要么找占用内存的进程。
2.2 swapon和/proc/swaps确认要关的是哪个设备
一台机器可能有多个swap设备,有swap分区也有swap文件。先看清楚再动手:
bash复制swapon --show
输出示例:
text复制NAME TYPE SIZE USED PRIO
/dev/sda3 partition 8G 4.2G -2
/swapfile file 4G 1.8G -3
这说明系统里同时启用了分区交换区/dev/sda3和文件交换区/swapfile。如果不带参数执行swapoff,它会默认关闭/dev/sda3,但你可能想关的是/swapfile,或者想两个一起关。所以第一步必须明确自己的目标。
也可以查看/proc/swaps文件,内容本质上和swapon --show一样:
bash复制cat /proc/swaps
我个人的习惯是用/proc/swaps做脚本判断,因为文件解析起来更容易。
2.3 swapoff成功率取决于一个数字
核心理念清楚后,可以给自己定义一个判断标准:只有在available内存 >= swap已用量 + 一定安全余量时才执行swapoff。安全余量我一般留2G,因为操作系统和正在运行的进程随时可能申请新的内存,不留余量容易触发OOM。
比如说swap used是6G,available只有7G,那我至少会先做一步清理再关,把内存余量拉到8G以上。怎么清理?优先考虑系统的可回收缓存。可以用:
bash复制echo 3 > /proc/sys/vm/drop_caches
drop_caches接受1、2、3三个值,1表示释放page cache,2表示释放目录项和inode缓存,3表示两者都释放。这是比较温和的缓存回收方式,不影响进程数据。不过提醒一句:在生产环境执行这个操作前最好确认你的业务对页缓存不敏感,而且不要频繁执行,它只能作为应急手段,不是日常优化方法。还有另一种问题定位思路:通过top或ps找出swap占用大户,杀掉这些进程来退出内存空间:
bash复制top
然后按shift+O,再按p,让进程按内存排序。Linux下没有直接一键看进程swap占用量的命令,但可以用脚本遍历/proc目录计算,这个方法网上有现成的轮子,这里不展开。
3. swapoff的语法和参数拆解
明白了前置条件,再回到命令本身。swapoff属于util-linux软件包,几乎所有的Linux发行版都自带,不需要额外安装。语法很朴素:
bash复制swapoff [选项] [交换设备或交换文件]
3.1 常用参数与实际含义
我自己真正用到的参数其实就两个:-a和-v。
bash复制swapoff -a
-a表示all,关闭所有在/proc/swaps中标记为active的交换设备。这个参数的好处是一把梭,不用一个个指定设备名,适合机器里只有一个swap区或者想全部关掉的场景。风险点也在“一把梭”——如果内存余量不够承载所有swap设备里已用的总和,命令会失败,各设备状态可能处于部分关闭、部分未关闭的中间态。
bash复制swapoff -v /dev/sda3
-v打印详细执行信息,比如:
text复制swapoff /dev/sda3
不带任何参数的swapoff和-v效果是一样的,只是输出没那么详细。在脚本里如果想捕捉执行是否成功,用-v反而更好,因为你能在日志里看到到底是哪个设备执行失败了。
其他参数还有-h帮助和-V版本,这两个用途就不说了。通常日常运维用到的就这么多。
3.2 用设备名、UUID还是文件路径
参数里指定swap区的方式有讲究。直接用设备名最直观,但有一个隐患:设备名在某些环境下不可靠,比如有多个磁盘时/dev/sda在重启后可能变成/dev/sdb,这会导致swap挂载错乱。所以更稳妥的做法是用UUID。
先查询swap分区的UUID:
bash复制blkid /dev/sda3
得到输出后,可以这样关:
bash复制swapoff UUID=xxxx-xxxx-xxxx
不过说实话,日常手动操作时我几乎总是直接写设备名或者文件路径。但在写自动运维脚本、批量操作多台机器时,UUID更可靠。如果是swap文件,则直接写完整路径,比如swapoff /swapfile。这点记住就行,遇到对应场景自然就知道该怎么选。
这里顺便确认为什么操作系统能识别这些不同写法:内核通过设备的主设备号和次设备号识别交换设备,无论你给的是设备名还是UUID,用户态命令最终都会换算成对应的设备号,所以效果上没有区别,区别只在于路径的稳定性和可读性。
4. 实测流程:从关闭单个交换区到永久禁用
这部分是全文的重头戏,我把一份可以照着走的完整操作流程写出来,从最基本的单个swap关闭,到永久禁用,再到systemd环境下的特殊情况处理,全部过一遍。
4.1 单分区/单swap文件的关闭操作
假设当前机器上只有一个swap分区/dev/sda3,执行:
bash复制swapoff /dev/sda3
没有任何输出,没有报错,表示成功。可以用free -m确认:
text复制Swap: 0 0 0
总容量变为0,说明已关闭。如果是swap文件:
bash复制swapoff /swapfile
操作本质上是一样的。关闭单个交换区是常规操作里最安全的,因为系统里可能还有其他swap设备在,完全不担心内存问题的前提下,这个操作极少失败。
4.2 全部swap一起关,以及修改fstab实现永久禁用
全部关闭的操作:
bash复制swapoff -a
执行完同样用free命令检查。但这还没完,这一节最重要的部分来了:如果你只执行swapoff,系统重启之后swap会回来。原因在/etc/fstab文件里,系统每次启动都会按照这个文件清扫并重新挂载交换设备。所以要永久禁用,必须改fstab。
先备份:
bash复制cp /etc/fstab /etc/fstab.bak.$(date +%F)
然后用编辑器打开fstab,找到包含swap关键字的行,以注释的方式禁用,或者直接删掉:
bash复制# /dev/mapper/centos-swap swap swap defaults 0 0
如果你用的是swap文件,对应那一行类似:
bash复制# /swapfile none swap sw 0 0
改完保存。重点提示:不要直接卸载fstab里仍在生效的行而不作修改就重启,否则启动过程会等待swap挂载超时,拖慢开机速度甚至进入紧急模式。这个坑我遇到过一次,当时忘了备份直接改错了行,重启后系统直接进了emergency mode,处理起来非常麻烦。
4.3 systemd环境下的特殊处理
现代Linux发行版基本都是systemd管理服务。systemd会根据fstab自动生成swap单元,所以有时你明明swapoff了,过一会儿一看swap又自动激活了——这就是systemd在搞鬼。
遇到这种情况,先看系统注册了哪些swap单元:
bash复制systemctl --type=swap
输出会列出swap单元名称,比如swap-dev-sda3.swap或swapfile.swap。需要禁用对应的单元:
bash复制systemctl mask swap-dev-sda3.swap
mask命令会创建一个指向/dev/null的符号链接,让这个单元无法以任何方式启动。这是比disable更彻底的手段。不过在我的经验里,改动fstab之后重启机器,mask不mask其实结果都一样——fstab里没有对应条目,systemd就不会生成swap单元。操作顺序上建议先改fstab,再mask,双保险。
4.4 关闭swap后如何验证是不是真的关干净了
验证关闭状态有三个层次,从浅到深:
第一层,free -h:
bash复制free -h
看Swap总容量是否为0或只剩未关闭的其它swap。第二层,直接查看正在生效的swap设备列表:
bash复制cat /proc/swaps
没有任何输出行(除了头部Filename开头的标题行),说明系统当前没有可用的交换区。第三层,重启之后再做一次前面两个命令,确认fstab修改是否生效、swap有没有复活。
还有一种情况是云主机使用基于文件或逻辑卷的swap,验证时还要看一下LVM卷是否存在但未激活,用lvs命令确认。总之验证的标准是:当前无活动swap,重启后依然无活动swap。做到这两点,永久禁用才算真正落地。
5. swapoff失败或卡住时的排查思路(基于真实踩坑)
操作本身不难,难的是操作失败之后的处理。我这里把自己实际遇到过的几种异常情况完整的排查链路写出来。
5.1 内存不足导致失败时的完整处理链路
真实执行时,swapoff返回错误提示可能是:
text复制swapoff: /dev/sda3: swapoff failed: Cannot allocate memory
这是最典型的失败场景。它意味着内核尝试把swap中的内存页搬回RAM,但物理内存可用页不够。看到这个报错,走下面的排查和解决路径:
第一步,重新用free -m确认内存数据。对比available和swap used。
第二步,检查是不是有进程占用了大量内存。用top按内存排序,记下内存占用最高的几个进程PID。
第三步,如果有明确可以重启或迁移的应用进程,直接处理这些进程释放内存。如果是MySQL这类不能随便重启的数据库,可以临时把innodb_buffer_pool_size调小,或者用ALTER TABLE之类的DBA指令把缓冲占用的内存释放出来,再执行swapoff。
第四步,如果暂时找不到合适的进程可以处理,可以尝试回收系统的page cache:
bash复制sync; echo 3 > /proc/sys/vm/drop_caches
这一步把不用的缓存释放出来,运气好的话能腾出足够空间。
最后,如果所有手段都用了内存还是不够,回到更早的检查环节:这台机器物理内存是真的不够,不是优化能解决的。这时候最稳妥的办法是先临时增加一台机器把负载分流,或者增加物理内存之后再来处理swap。硬关swap造成OOM killer触发,后果比磁盘紧张严重得多。
5.2 swapoff执行了很久都不结束怎么办
swapoff在某些环境下不是瞬时的,尤其当swap里装的数据量很大时,它需要在磁盘和内存之间拷贝大量数据,这个过程会持续几十秒甚至数分钟。有一次我在一个64G内存的机器上,swap用了大约11G,执行swapoff之后等了将近四分钟才完成。期间机器IO处于密集读状态,命令行为看起来像卡死,其实是正常的。
判断它是否还活着,可以从另一个终端观察内存变化:
bash复制watch -n 1 free -m
如果看到Swap的used值在持续下降、available在下降(数据搬回内存)、buff/cache在变化,说明交换区在正常回流,耐心等就好。如果长时间数值纹丝不动,再考虑是不是IO卡住或者内核异常,此时可以看dmesg输出有没有异常:
bash复制dmesg -T | tail -50
如果看到大量跟内存回收或IO错误相关的信息,那就不是等待能解决的,需要对症处理。但说实话,绝大多数swapoff耗时长的案子,都是因为卷比较大、磁盘比较慢,没有捷径,只能等。
5.3 我踩过的另外两个小坑,一并提醒
第一个坑是“当前工作目录在swap文件所在的文件系统上”。有一次我写脚本时把当前目录cd到了/swapfile所在目录,执行swapoff时报错设备正忙。原理解释起来很绕,简单说就是进程的当前工作目录或文件引用会导致文件系统无法干净卸载。处理办法是把当前shell切到别的目录,比如cd /root,然后重新执行。
第二个坑是云主机控制台的“swap是云平台配置的”。有些云厂商的Swap是平台定义好的,你改完fstab、执行完swapoff,下一次云平台初始化可能又给你挂回来了。遇到过阿里云和腾讯云一些旧型号实例有这个行为,排查了很久才发现是平台层面在启动时注入了配置。解决办法是到云控制台或通过初始化脚本检查是否有相关的用户数据或配置注入,清掉对应配置。
6. 实操过程中值得保留的几条经验和建议
这部分算是我这几年和swap打交道攒下来的一些心法,不追求面面俱到,只写实际帮过我的。
6.1 关掉swap后一定要调整swappiness,否则效果有限
swappiness是内核参数,控制内核把内存页交换到swap的“积极程度”,取值范围0到100,默认通常是60。如果你关闭了swap,这个参数其实没有直接影响;但在那些不能完全关闭swap、只能优化使用策略的场景里,调整这个参数才是核心手段。
比如你希望系统尽可能多用物理内存,少用swap,可以设置:
bash复制sysctl vm.swappiness=10
或者直接写进/etc/sysctl.conf永久生效:
text复制vm.swappiness=10
设置完之后,即使swap平时还是挂载着的,内核也不会动辄就把数据往swap里搬,数据库类应用的访问延迟会明显下降。我的实际测试里,一台16G内存的MySQL服务器,swappiness从默认60改到10之后,swap使用量从日常3G左右降到了几百MB,慢查询数量也有可见下降。这个参数和swapoff经常成对出现,建议一起掌握。
6.2 关闭swap后磁盘空间如何回收
swapoff之后,原来swap占用的磁盘空间不会自动回到你的可用空间列表里。根据swap类型,处理方式不一样:
如果是独立swap分区,可以用fdisk把对应分区删除,然后扩展相邻分区,或者新建分区挂载为其他用途。但涉及根目录空间的扩展操作有一些风险,操作前务必备份分区表信息。
如果是LVM逻辑卷上的swap,可以用lvremove删除逻辑卷,再把空间扩展给根文件系统。大致步骤如下:
bash复制lvremove /dev/vg0/swap
lvextend -l +100%FREE /dev/vg0/root
xfs_growfs /
如果你用的是ext4文件系统,对应调整resize2fs。这套操作我在测试环境试过多次,成功率很高,但每台机器的卷组名、逻辑卷名大概率不同,一定要先确认名称,不能照抄。
如果是swap文件,那就最简单,直接:
bash复制rm -f /swapfile
删除前确认swapon --show里已经没有这个文件了。另外提醒一句:关swap之后,/etc/fstab里的对应行如果不删,重启时系统会试图挂载一个不存在的swap设备,导致开机报错。所以改fstab这步永远不能漏。
6.3 关swap之前建议做的一次完整演练
我自己后来养成了一个习惯,重要机器的swap操作一定先演练一遍。具体做法是:在非生产环境或备用节点上,先完整运行一遍“检查-关闭-验证-回滚”,确认操作步骤和预期一致,再上生产。
演练中的回滚可以这样理解:临时关闭swap的操作是幂等的,重新启用只需一条:
bash复制swapon /dev/sda3
在没改fstab的前提下,重新挂载swap设备会把它拉回可用状态。如果改过fstab,先还原fstab再swapon。保持一个可回滚状态,是生产操作的基本素养。
最后一句话送给大家:swapoff不是一条孤立命令,它只是一个动作,背后是内存预算、磁盘资源、系统初始化机制三者的综合操作。先理解再动手,才是运维该有的节奏。
