ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu Swap扩容实战:swap文件与分区配置详解

Ubuntu Swap扩容实战:swap文件与分区配置详解 1. 为什么要折腾swap先搞清楚它帮你扛住了什么很多人一听swap扩容第一反应是“内存不够了就加点swap呗”这话对但也不全对。我刚接触Ubuntu那会儿也这么想直到一次生产环境上的Python任务把内存干到100%系统直接OOM把进程杀掉日志都没来得及落盘才意识到swap不只是“慢速内存”这么简单。它更像一个兜底阀当物理内存被占满时内核会把一部分不常用的内存页换到磁盘上腾出空间给活跃进程用。没有这个兜底阀系统只能启动OOM Killer谁内存占用大就杀谁你可能连保存文件的机会都没有。所以swap扩容这件事本质上是给系统的“内存压力泄洪通道”加宽。在Ubuntu上操作swap主要有两条路线一是直接调整swap分区大小二是创建一个swap文件来补充。两者都有人用但偏好差异很大。我自己在云服务器和本地开发机上反复试过如果你问我哪条路更适合大多数人我会推荐swap文件。原因后面细说这里先聊一个更根本的问题你到底要不要扩swap。判断标准很简单先看你的使用场景。跑数据库、编译大型C项目、开多个Docker容器、跑深度学习推理这些场景内存峰值高扩swap能显著降低被杀进程的概率。如果你只是浏览网页、写写文档物理内存常年用不满那扩swap的意义不大反而浪费磁盘空间。另外还要看你的存储类型机械硬盘上的swap效果很一般SSD/NVMe上的swap文件体感会好不少因为随机读写延迟低。我自己的习惯是桌面机16GB内存配8GB swap服务器32GB内存配16GB swap数据库机直接关掉swap用swapiness调优来兜底。这个比例不是拍脑袋后面我会讲怎么算。再说一个常被忽略的点很多人扩容swap是为了解决“内存不足”报错但报错并不一定都靠扩容解决。有时候是某个进程内存泄漏比如Java程序的堆设置太大或者Jupyter Notebook打开太多内核。这时候扩容swap只是把问题往后拖该限制的进程还得限制。所以动手之前先看一眼内存和swap的实时占用心里有数再决定要不要扩。我这里说的“实时占用”就是在终端里跑一个命令就能看到具体命令下一节讲。你只需要记住swap扩容是一个系统级操作动的是磁盘布局或者系统文件操作前备份永远没错。后面我会把从查看、创建、挂载、开机自启到回滚的完整流程都写清楚你跟着一步步来基本不会踩坑。2. 动手前先看清家底确认分区布局和当前swap状态2.1 三条命令快速摸清现状扩容之前你至少要知道三件事当前swap用了多少、系统里有没有swap分区、磁盘上还有没有空余空间。这三件事分别用三个命令就能查清楚终端里依次跑一下第一个是free -h它告诉你内存和swap的总量、已用量和剩余量。重点关注Swap那一行如果used长期超过50%说明系统确实在频繁使用swap扩容是有价值的。如果used一直是0那说明物理内存充足你可以暂时不折腾。第二个是swapon --show它列出当前生效的swap设备或文件。输出会包含设备路径比如/dev/sda2或/swapfile、类型partition或file、大小等。如果这个命令输出为空说明系统压根没启用swap你直接创建就行了。第三个是lsblk它把磁盘分区结构列出来让你知道根分区在哪块盘上、哪块盘还有空余空间。这个命令的输出很直观第一列是块设备名后面是容量、挂载点。三连查完基本就能确定方案。这里先说一个我踩过的坑有些云服务器默认只有一个小swap分区在lsblk里看是一块单独的小分区比如2GB它的前后空间都被LVM卷或主分区占满了没有未分配空间。这种情况下你是没法原地扩大这个分区的要么新建一个大分区要么直接用swap文件。这也是我推荐swap文件的原因之一——它不受分区布局限制。2.2 两种扩容路线的本质区别老规矩先看路线图再动手。扩容swap有两条主流路线分区扩容和swap文件扩容。分区的本质是改磁盘分区表把某个swap分区删掉重建或者把相邻空闲空间扩展进去操作完成后用mkswap重新格式化再swapon启用。它的优点是性能好因为分区在磁盘上可以是连续块对机械硬盘来说顺序读写有优势缺点也很明显操作风险高、灵活性差。一旦分区表改错你整个系统的引导都可能会挂尤其是根分区在独立LVM卷上的场景扩展逻辑卷反而更麻烦。swap文件的本质是创建一个普通文件把它当作块设备一样格式化并启用。它可以是任意大小放在你希望的位置比如根目录/swapfile或/var/swapfile系统启动时通过/etc/fstab自动挂载。它的性能在现代SSD上并不比分区差多少而且扩容、缩容都很方便删掉重建就行了不用动分区表。如果想调整大小直接swapoff这个文件、删掉、按新大小fallocate再mkswap重新启用一分钟搞定。选哪种我给你的建议是跑在SSD上的系统无脑用swap文件省心而且回滚方便跑在传统机械盘上的老机器如果内存又小那么swap文件在长时间高负载下会有明显的性能衰减这种环境建议优先考虑分区方案或者把swap文件分散到多块盘上缓解竞争。当然如果你用的是LVM逻辑卷那第三种玩法是用lvresize来扩容逻辑卷但虚拟化环境或云主机上未必有LVM这里我就不过多展开了。2.3 扩容前必须备份的几个位置我之前有段时间手贱在没有备份的情况下对一个正在使用的swap分区执行了swapoff结果发现那个分区还被某些进程占用swapoff的过程中系统内存立刻告急最终不得不重启。所以扩容前备份这件事要当成强制规定。重点备份三个位置/etc/fstab、磁盘分区表、重要的数据文件。/etc/fstab是挂载配置里面记录了swap分区或swap文件的挂载方式。如果分词操作失误导致系统无法挂载root分区恢复fstab能救你一命。备份它很简单sudo cp /etc/fstab /etc/fstab.bak.$(date %Y%m%d)这样每次操作前都会留下一个带时间戳的副本。磁盘分区表用gdisk或fdisk的备份功能导出比如sudo sgdisk --backup/path/to/table.bak /dev/sda这条命令把整块盘的GPT分区表保存到指定文件万一你删错了分区可以用sgdisk --load-backup恢复。数据文件就不用我多说了自己心里有杆秤。肉眼可见的原则就是在做任何涉及分区的写操作之前至少先看一眼fstab备份文件存在了没有。完成这三步后你就能放心进入正题了。接下来我给两套实操流程先讲swap文件方案再讲swap分区方案。你只需要挑一套适合自己环境的照着执行。3. 最推荐的扩容方案用swap文件完成扩容不碰分区3.1 准备工作确认目录和磁盘剩余空间创建swap文件前先确认你打算把它放在哪个目录。最常见的是放在根目录/下如果根目录空间紧张也可以放到/var或/home。但是有一个关键点这个目录所在的文件系统必须支持fallocate或truncate创建文件并且权限允许root写入。默认的ext4、xfs、btrfs都有没问题。如果根目录剩余空间不够就需要换一个分区。查看磁盘剩余空间可以这样df -h /看到Avail那一列就是当前目录挂载分区的可用空间。假设你有16GB内存想扩8GB swap那根目录至少要有8GB空余稳妥点留到12GB以上因为除了swap你还需要一点点临时文件空间。如果空间不够可以选其他盘关键是路径在哪个挂载点下就用对应的df -h /path确认。3.2 创建swap文件两种方式以及它们的小坑创建swap文件有两种主流方法fallocate和dd。先说fallocate它是现代文件系统的快速分配方式只调整文件大小标记不实际写数据速度飞快sudo fallocate -l 8G /swapfile但这个方法有一个隐藏坑如果在某些文件系统上比如部分老旧的ext3、或是特殊配置的ext4fallocate创建的文件可能会带着“孔洞”也就是逻辑上占8G但实际只有部分物理块分配了空间。用它做swap文件虽然mkswap能成功但使用一段时间后可能会因为底层物理块不足导致I/O错误。所以更稳妥的方式是dd把文件里的内容全部置零强制分配真实块sudo dd if/dev/zero of/swapfile bs1M count8192 statusprogress这里bs1M是块大小count8192就是8GB8192MB。如果你想要4GB就把count改成4096。dd这种方式慢一点但对绝大多数文件系统来说都是纯物理分配安全系数更高。我个人的习惯是生产环境用dd个人开发机如果磁盘空间充足也可以用fallocate省时间。两者选一之后就进入下一步。3.3 权限设置、格式化和启用创建完/swapfile之后先调整权限。swap文件如果可以被普通用户读取信息会暴露在/proc里虽然不至于泄漏太多秘密但安全习惯总是好的。执行sudo chmod 600 /swapfile然后格式化这个文件让它变成swap格式sudo mkswap /swapfile命令输出会显示“Setting up swapspace version 1...”之类的内容说明成功了。接下来启用它sudo swapon /swapfile然后验证一下是否生效sudo swapon --show free -h看到/swapfile出现在列表里并且free -h的Swap总量变大就说明这次扩容已经生效了。这里插一句如果你系统本身有swap分区现在又加了个swap文件系统会同时使用这两个swap空间优先级由swapon的pri参数决定。默认情况下内核会按优先级顺序填充swap通常分区优先级更高所以不额外设置也没问题。如果你想让swap文件优先可以指定sudo swapon -p 10 /swapfile数字越大优先级越高。3.4 让系统重启后自动挂载swap文件手动swapon只在当前系统运行期有效重启后就会丢失。要让开机自动启用需要把swap文件写进/etc/fstab。用编辑器打开文件在末尾追加一行/swapfile none swap sw 0 0这行配置的格式是设备路径、挂载点swap用none、文件系统类型swap、挂载选项sw、dump标志、fsck顺序。这是最标准的写法。保存后重启系统就会自动启用/swapfile。如果想要严谨验证一下fstab有没有写错可以执行sudo mount -a该命令会根据fstab尝试挂载所有尚未挂载的条目如果这行配置有路径错误它会直接报错趁系统重启前发现。3.5 swap文件扩容与缩容的完整回滚方法swap文件的好处就是随时可以调整大小。假设你原本建了8G跑了两周觉得不够想扩到16G步骤是sudo swapoff /swapfile// 停用该项sudo rm /swapfile// 删掉旧文件按照3.2和3.3重新创建16G的swap文件权限和mkswap再次走一遍确认fstab里的路径没变如果路径变了就更新fstabsudo swapon /swapfile// 重新启用这个流程很快所以如果你不确定需要多大可以先建一个小一点的跑一跑看峰值占用再动态调整比一开始就建一个巨大的swap文件要灵活得多。不过有一点要提醒swapoff会把swap里的数据全部换回物理内存如果物理内存已经不够swapoff可能会卡死甚至触发OOM。所以在缩小swap文件之前最好先确认有足够空闲物理内存来承接这些换回的数据。可以用free -h看如果available小于swap文件里当前占用的用量就先别急着swapoff让系统自己慢慢把数据换出或者等内存压力缓解后再操作。4. 扩容swap分区传统分区方案的操作细节4.1 查看分区布局与决定扩展目标说完了swap文件再说回传统分区方案。什么时候你不得不走这条路硬件上还是老机械盘且内存只有4G或更少系统负载又稳定swap文件在磁盘上的随机读写会形成持续瓶颈这时候swap分区因为顺序分配和独立位置抗负载能力会好一些。另外如果你在云控制台创建的虚拟机是标准镜像默认已经带了swap分区你也可以在原分区上直接扩容毕竟分区表结构就是现成的。操作前先看当前分区布局sudo parted /dev/sda print freeparted命令会把分区和未分配空间都列出来。如果你看到swap分区后面恰好跟着一段“空闲”空间那就是扩分区的最好条件。如果你用的是LVM管理比如/dev/mapper/ubuntu--vg-swap那不用管底层物理分区直接用lvresize扩展逻辑卷就完事。但大部分人遇到的是普通分区表我们就按普通分区来。4.2 使用growpart原地扩展分区GPT分区表推荐如果你的swap分区后面刚好有空闲空间最安全的操作不是删分区重建而是原地扩展分区。工具用growpart它专门用来扩展GPT和MBR分区表而无需重建分区sudo growpart /dev/sda 分区号比如swap分区是/dev/sda2分区号就是2执行sudo growpart /dev/sda 2执行完它会告诉你分区从多少扇区扩展到了多少扇区。这一步不存在删除分区所以风险极小。但前提是分区表类型是GPT并且分区后面有未分配空间。要是没有就得用下面这种“亡羊补牢”式的重建方案。因为重建分区会清掉swap数据所以必须在swapoff的状态下做。4.3 使用fdisk重建swap分区MBR场景如果你的盘是MBR分区表或者swap分区前后都没有空闲空间办法只剩下删除原swap分区在原位置创建一个更大的分区。这意味着你手上得有一块“备用领地”——要么同一块盘上有空闲空间要么换一块盘。这里以同一块盘上有空闲空间为例操作流程是先停用swapsudo swapoff /dev/sda2打开fdisk /dev/sda输入p查看当前分区表和起始扇区记录下swap分区的起始和结束扇区输入d删除该分区但注意删除后不要立刻写盘。先输入n新建分区起始扇区必须和原来一致否则数据全毁结束扇区选到空闲空间的末尾输入t把分区类型改成Linux swap类型ID是82GPT下是swap或0657然后w写盘重新格式化sudo mkswap /dev/sda2启用sudo swapon /dev/sda2这套流程最怕的就是删分区后没对准起始扇区。所以再次强调fdisk的p输出里的start值一定要记下来。如果你不确定可以用sudo parted /dev/sda unit s print切换成扇区单位查看扇区级别的精度足够准。4.4 LVM逻辑卷扩容swap的捷径如果你的Ubuntu安装过程中使用了LVM很多桌面安装器的默认选项就是“使用了整个硬盘并启用LVM”你会发现swapon --show里的设备是类似/dev/mapper/ubuntu--vg-swap_1的路径。这种场景扩swap根本不用碰fdisk直接用LVM命令即可。先查一下卷组里的空闲空间sudo vgdisplay看Free PE / Size一项假如还有5GB空闲那就可以把swap逻辑卷扩展5GBsudo lvextend -L 5G /dev/mapper/ubuntu--vg-swap_1扩展逻辑卷后swap逻辑卷底层的物理卷空间变大但文件系统还是旧的swap格式所以你需要重新执行mkswap让它识别新大小sudo mkswap /dev/mapper/ubuntu--vg-swap_1 sudo swapon -aLVM方案最大的好处是不需要删分区、不需要担心起始扇区风险跟swap文件差不多低。如果你刚装上服务器强烈建议规划时就用LVM把swap做成逻辑卷后续扩容真的是一行命令的事。不过LVM也有缺点如果在虚拟化环境下开启的底层盘不支持在线扩展你得先把物理卷的容量扩出来工具就复杂一些。我这里就不深入了只说结论能用LVM就用LVM。4.5 分区扩容后的挂载配置检查无论是上面哪种方式扩容完分区都别忘了确认fstab里的配置仍然指向正确的设备路径。用blkid查一下设备的UUID把fstab里的对应行改成UUID形式更稳sudo blkid /dev/sda2输出会带有UUIDxxxx再把fstab里swap那一行的设备路径替换成UUIDxxxx例如UUIDxxxx none swap sw 0 0为什么不建议直接用设备名因为设备名在插入U盘、加载其他磁盘时可能会变化比如/dev/sda变成/dev/sdb而UUID是分区自己的身份标识基本不会变。这是我在维护一台多块硬盘的机器时吃亏学到的。无论是swap文件还是swap分区fstab里用UUID或绝对路径都行但千万别写一个裸的设备短名。5. 调优swap率与开机自启的细节让扩容效果发挥到最大5.1 swappiness到底是什么调多少合适很多人扩容完swap就以为完事了其实还有一个关键参数会影响swap的真实效果——vm.swappiness。这个值范围是0到100代表内核“倾向使用swap的程度”。默认Ubuntu一般是60意思是内存使用超过一定阈值后内核会倾向于把内存页换出去一些来保持物理内存有更多空闲。但60这个值对桌面用户、开发机来说偏高了很容易导致你刚打开几个应用内存明明够系统却开始频繁读swap卡顿感非常明显。我个人的调查结论是桌面Ubuntu调到10左右比较舒服服务器可以20上下。调低不等于禁用swap只是让内核优先使用物理内存直到内存真正紧张才用swap。如果内存常年不够你调很低也没啥用因为它最终还是得swap。如果你压根不想用swap可以设为0但我不建议完全关闭除非你确认物理内存永远够。临时调整可以用sudo sysctl vm.swappiness10永久生效需要写进配置文件echo vm.swappiness10 | sudo tee /etc/sysctl.d/99-swap.conf重启后也会自动生效。另外还有一个vm.vfs_cache_pressure参数控制内核回收目录项和inode缓存的倾向。默认100我觉得对于桌面没必要动如果你跑大量小文件I/O服务可以降到50能减少inode缓存回收频率对提高小文件操作请求命中率有帮助。这个不算swap的核心配置但和内存交换有关联一并提一句。5.2 开机自动挂载的两种写法与验证前面提到swap文件要写进fstab才能开机自动挂载。但这里有个细节很多人踩坑用fallocate创建的swap文件建议在fstab里用discard选项如果底层支持或者在创建时用swapon --discard来允许TRIM对SSD寿命有帮助。写fstab时你可以把swap文件那一行改成/swapfile none swap sw,discard 0 0但对swap分区来说discard选项不适用而且某些老内核可能不支持。为了稳定我一般不在fstab里写discard而是用cron定时执行sudo fstrim /来定期清理空闲块。这个属于旁支不展开。还有一种开机自启的写法是用systemd挂载单元但我个人认为fstab针对swap已经足够了毕竟fstab是内核自带的机制systemd也会解析它。如果你在fstab里配置了swap文件但开机没生效常见原因有两个一是fstab里的文件路径和实际文件路径不一致二是开机时那个文件系统的挂载顺序排在swap之后。解决办法是把swap条目放在根目录挂载条目之后即可默认顺序通常没问题。5.3 多大swap合适用公式给你一个参考值很多新人在社区问“多大swap算合适”我一般给一个参考公式再讲例外。通用公式swap大小 物理内存的50%到100%最大不超过16GB。物理内存小于4GB的swap可以用内存的两倍4GB到16GB内存swap取内存的一半或等于内存16GB以上内存swap一般8GB到16GB就足够了除非你跑超大内存应用。为什么有这个上限因为swap太大并不能降低浪费反而占磁盘。如果你内存都64GB、128GB了swap基本是应急用途16GB足够覆盖极端分配场景。公式是死的场景是活的。如果你跑Redis或MySQL这类对内存响应极其敏感的应用swap过大反而可能让进程长期“睡着”在swap里恢复响应时延迟暴增。这种情况我宁愿把swap设小让大内存应用尽量留在物理内存里。反之如果你是搞深度学习的显存不够、CPU内存也多建议swap设成和内存等大因为推理时的临时张量分配是burst式的有swap在进程至少不会被立刻杀掉甚至能坚持到你把一个batch跑完。6. 常见问题与排查实录6.1 swapon失败无效参数或权限不足新人在创建swap文件后执行sudo swapon /swapfile偶尔会碰到“swapon: /swapfile: 无效参数”。原因很可能是文件落在一个不允许swap的文件系统上比如某些网络文件系统或压缩文件系统。解决办法是先确认你落在哪个挂载点换成ext4或xfs目录。还有可能是文件带有sparse hole就是你用fallocate创建的导致内核拒绝这种就用dd重造。最后检查文件权限是不是600root权限是否足够chmod 600 /swapfile和sudo -i都试一下。6.2 开机后swap没有自动启用fstab里明明写了重启后free -h一看swap还是0这种情况多半是fstab语法问题。把挂载选项的sw误写成了swap或者设备路径写错。排查步骤是systemctl status swap.target journalctl -u systemd-fstab-generator看看报错信息。通常日志会明确提示“Failed to find the hidden ...”这时检查路径和权限。还有一点容易被忽略如果你把swap文件放在了加密目录或非root自动挂载的目录里开机时那个文件系统可能还没来得及挂载swap自然挂不上。要么把swap文件移到根目录要么在fstab里加上x-systemd.requires-mounts-for/path。6.3 swapoff卡住不动系统内存很满执行swapoff /swapfile时内核要把swap里的数据搬回物理内存这个过程是同步且阻塞的如果物理内存不够放swapoff就可能长时间不返回。遇到这种情况最稳的做法是别傻等按CtrlZ强制回终端不过它不会停止内核线程然后重新用sysctl vm.drop_caches3丢弃部分缓存以腾出内存再试一次swapoff。实在不行重启机器最干脆她毕竟不会因为swapoff失败就死机。6.4 OOM还是发生了swap用完但内存照杀有一种情况是swap明明扩容了但OOM Killer还是触发。原因是OOM判定不仅要看swap总量还要看进程的“可回收页”指标。当物理内存耗尽内核会尝试回收文件映射页等这部分内存不占swap如果物理内存因匿名页占满匿名页必须换到swap而swap也确实满了那就只能杀了。所以swap扩容能降低OOM频率但别指望它能完全免死。这时要么减内存占用要么研究一下/proc/sys/vm/overcommit_memory和vm.overcommit_ratio对过量分配内存的进程做限制。6.5 如何安全的从swap文件回退到原状态想要撤销swap文件的影响步骤是sudo swapoff /swapfile sudo rm /swapfile同时把fstab里那一行删除或注释掉。刚才保留的fstab备份就能派上用场直接cp恢复也行。但如果你只是临时测试不想要了直接删除文件即可下一次重启不会自动挂载。唯一要注意的是如果删除文件前还有进程占用swap这个文件虽然看不见了但它仍然由内核引用不会释放磁盘空间。必须等swapoff完成文件引用计数归零才能真正释放。这也是很多人“删了swap文件但磁盘空间没回来”的原因。6.6 打包一份速查表我把涉及的核心操作整理成一个表方便你平时快速查参考操作场景关键命令注意事项查看当前swapfree -h或swapon --show确认used与size查看分区布局lsblk或parted /dev/sda print free找到空闲空间创建8G swap文件sudo dd if/dev/zero of/swapfile bs1M count8192 statusprogress磁盘要有对应空间设置权限sudo chmod 600 /swapfile必须600格式化swap文件sudo mkswap /swapfile成功后可用启用sudo swapon /swapfile避免和已有分区冲突可指定-p优先级永久挂载在/etc/fstab追加/swapfile none swap sw 0 0重启后验证调整swappinesssysctl vm.swappiness10写配置文件可持久化扩展swap分区GPTgrowpart /dev/sda 2后重新mkswap需要分区后有空闲扩展swap逻辑卷lvextend -L 5G /dev/mapper/vg-swap后mkswap需要卷组有空闲缩容swap文件swapoff→rm→重建 →swapon确保内存足够承载换出数据这张表基本覆盖了日常90%的场景。另外我建议每台机器设置完swap后都顺手建一个systemd服务或者用一个简单的监控脚本每天定时把内存和swap的使用量记到日志里这样能帮你复盘到底扩容够不够用不用等到爆内存才回头找数据。最后再分享一个我自己的小习惯做完swap扩容我会在/root/swap-notes.txt里写一行记录包括日期、原swap大小、新swap大小、用的是文件还是分区、为何调整。这个笔记在三个月后你根本想不起来当初为啥这么调的时候能省下大把排查时间。Linux系统管理就是这样每一步操作都有成本但把状态管理好、把原因记录好后续维护就会越来越轻松。
返回列表