
1. 项目概述为什么 Ubuntu 18.04 用户今天仍需亲手配置 Swap 空间Ubuntu 18.04 是一个被大量生产环境、开发工作站和老旧硬件设备长期依赖的 LTS 版本它自带的安装器在默认配置下往往不创建 swap 分区尤其当系统内存 ≥ 4GB 且检测到 SSD 时安装程序会直接跳过 swap 配置——这个“善意”的自动化决策在真实使用中却埋下了不少隐患。我见过太多用户在编译大型项目、运行 Docker 多容器、开启 Chrome 十几个标签页后系统突然卡死、鼠标失灵、终端无响应最后发现free -h输出里 swap 行赫然写着0B。这不是内存不够用而是系统彻底失去了内存压力缓冲机制。Swap 不是“备用内存”它是 Linux 内存管理中不可或缺的压力释放阀和OOMOut-of-Memory杀手的保险丝。当你看到dmesg | grep -i killed process出现chrome,code,java这类进程名时基本可以断定 swap 缺失是根源。Ubuntu 18.04 的内核4.15.x 系列对 swap 的依赖逻辑非常清晰没有 swap内核就无法执行页面回收page reclaim的完整策略只能硬扛直到触发 OOM killer 强制杀进程。这和“让系统使用 swap”这种模糊说法完全不同——swap 必须被正确创建、格式化、启用并持久挂载否则它就是一纸空文。本文聚焦的就是这个最基础、也最容易被忽略的实操环节如何在已安装完成的 Ubuntu 18.04 系统上安全、高效、可复用地添加一块 swap 空间。它不涉及 LVM 或加密 swap 这类进阶场景而是针对绝大多数普通用户的真实需求快速补上那块缺失的“安全垫”。你不需要重装系统不需要动硬盘分区表甚至不需要重启——整个过程在 3 分钟内完成且全程可逆。如果你正用着一台 8GB 内存的老款 ThinkPad T480 跑着 ROS 和 Gazebo或者在树莓派 4B 上部署了轻量级 Kubernetes 集群又或者只是想让自己的日常办公机更稳一点那么这篇内容就是为你写的。2. 核心思路拆解为什么选 swapfile 而非 swap 分区fallocate 为何优于 dd在 Ubuntu 18.04 上添加 swap本质上只有两条技术路径创建独立的 swap 分区swap partition或创建一个 swap 文件swapfile。前者需要修改磁盘分区表通常意味着要进入 Live CD 环境、用 GParted 调整分区大小、再重新安装引导风险高、耗时长、对新手极不友好。而后者即 swapfile 方案是 Ubuntu 官方自 17.04 起就主推的现代做法它把 swap 当作一个普通文件来管理完全绕开了底层分区操作。我之所以在所有客户现场和内部培训中都强制推荐 swapfile核心原因有三点第一原子性与可逆性。swapfile 是一个位于/或/home文件系统内的普通文件创建失败只需rm删除即可启用失败sudo swapoff /swapfile一行命令就能回滚没有任何副作用。第二空间灵活性。你可以把它放在任何有足够剩余空间的挂载点上比如外挂的 NTFS 硬盘需注意文件系统兼容性、大容量/home分区甚至是一个单独挂载的 ext4 数据盘。这直接回应了热搜词里“如何在外挂的硬盘中扩展 swap”的实际诉求。第三性能无损。很多人误以为 swapfile 比 swap 分区慢这是过时的认知。在 ext4/xfs 这类现代日志文件系统上一个预分配、无碎片的 swapfile其随机读写性能与 swap 分区几乎无差别。Linux 内核对 swapfile 的访问是直接通过 page cache 和 block layer 完成的不经过 VFS 的常规文件读写路径因此不存在额外开销。至于工具选择fallocate是绝对首选它比传统dd if/dev/zero of/swapfile bs1G count2快上百倍。dd是真的一字节一字节地向磁盘写零而fallocate只是在文件系统元数据层面“声明”这块空间已被占用瞬间完成且生成的文件是稀疏文件sparse file不实际消耗磁盘 I/O。但这里有个关键前提fallocate要求底层文件系统必须支持fallocate()系统调用Ubuntu 18.04 默认的 ext4 完全支持但如果你挂载的是 NTFS 或 exFAT比如外接移动硬盘fallocate就会报错Operation not supported此时就必须退回到dd方案。这也是为什么我在实操步骤里会明确写出两种方案的切换逻辑——不是为了炫技而是因为真实环境永远比文档复杂。另外mkswap的作用常被误解。它并非“格式化”swapfile而是向该文件写入一个特定的魔数magic number和校验信息让内核能识别出这是一个合法的 swap 区域。这个过程本身极快毫秒级但它却是 swap 启用前不可跳过的一步。跳过mkswap直接swapon系统会报错swapon: /swapfile: read swap header failed: Invalid argument这是内核在拒绝加载一个未签名的、不可信的 swap 区域。所以fallocate→chmod→mkswap→swapon这四步环环相扣缺一不可每一步都有其不可替代的内核级语义。3. 实操细节解析从零开始创建 swapfile 的每一步意图与避坑要点创建 swapfile 看似简单但每一步背后都有其严谨的设计意图和极易踩中的陷阱。下面我将逐行拆解标准流程并告诉你为什么必须这样写以及如果写错会怎样。3.1 创建文件fallocate 与 dd 的精确用法及适用场景第一步是创建文件本身。标准命令是sudo fallocate -l 2G /swapfile这里的-l 2G表示申请 2GB 的逻辑空间。注意2G必须是大写 G小写 g 会被fallocate解释为字节bytes-l 2g就等于 2 字节毫无意义。这个值不是随便定的。Ubuntu 官方建议的 swap 大小规则是内存 ≤ 2GB 时swap 2×RAM内存 2–8GB 时swap RAM内存 8GB 时swap 4–8GB 即可。对于一台 8GB 内存的机器2GB swap 是一个非常平衡的选择——足够应对日常多任务压力又不会因 swap 过大而拖慢swappiness调优效果。如果你的/分区剩余空间不足 2GBfallocate会直接报错fallocate: /swapfile: fallocate failed: No space left on device。此时你有两个选择一是清理/分区如sudo apt autoremove sudo journalctl --vacuum-size100M二是把 swapfile 放到其他挂载点比如/home。假设/home在独立分区且空间充裕命令就变成sudo fallocate -l 2G /home/swapfile但请注意/home下的 swapfile 在系统启动时可能因挂载顺序问题而无法被fstab正确加载这点我们后面会详述。如果fallocate报错Operation not supported说明当前文件系统不支持该调用常见于 NTFS、exFAT 或某些老旧的 ext3。此时必须改用ddsudo dd if/dev/zero of/swapfile bs1G count2 statusprogressstatusprogress参数至关重要它会在控制台实时显示写入进度避免你干等几分钟却不知道是否卡死。bs1G设为 1GB 块大小是为了最大化写入效率count2表示写入 2 个这样的块。dd的缺点是它真的会把磁盘填满所以务必确认目标分区有至少 2GB 的可用空间而不仅仅是“剩余空间”因为 ext4 的 reserved blocks 会占用一部分。fallocate则无需担心 reserved blocks因为它不写数据。3.2 权限加固chmod 600 的深层安全逻辑文件创建完成后必须立即设置权限sudo chmod 600 /swapfile600表示只有 root 用户可读可写其他所有用户包括同组用户和其他用户均无任何权限。这绝非形式主义。swapfile 的内容在交换过程中会包含进程的内存镜像其中可能含有密码、密钥、未加密的 API token、数据库连接字符串等高度敏感信息。如果权限过于宽松比如644任何普通用户都可以用strings /swapfile | grep -i password这类命令尝试从中提取明文信息。Linux 内核在swapon时会进行严格的权限检查如果 swapfile 的权限不是600swapon会直接拒绝并报错swapon: /swapfile: insecure permissions 0644, 0600 recommended。这个检查是内核硬编码的安全策略无法绕过。所以chmod 600不是一条可选命令而是一道强制性的安全门禁。3.3 初始化元数据mkswap 的不可替代性接下来是sudo mkswap /swapfilemkswap的作用是向/swapfile的开头写入一个 1024 字节的 swap 头swap header其中包含魔数SWAPSPACE2、版本号、校验和以及一些保留字段。你可以用hexdump -C /swapfile | head -n 1查看前几行会看到类似00000000 53 57 41 50 53 50 41 43 45 32 00 00 00 00 00 00 |SWAPSPACE2......|的输出。这个头是内核识别 swap 区域的唯一凭证。没有它swapon就像试图用一把没有齿纹的钥匙去开锁内核根本不会认。mkswap还会计算并写入一个简单的 CRC32 校验和用于在swapon时验证头的完整性。如果头损坏swapon会报read swap header failed: Invalid argument。值得注意的是mkswap不会清空文件内容它只修改开头的 1024 字节。所以即使你之前用dd写入的是随机数据mkswap之后swapfile 依然可以被安全启用。3.4 启用与验证swapon 的即时生效与状态确认启用 swap 的命令极其简洁sudo swapon /swapfile这条命令会立即将/swapfile注册为一个活动的 swap 区域整个过程毫秒级完成无需重启。启用后必须立刻验证是否成功sudo swapon --show正常输出应为NAME TYPE SIZE USED PRIO /swapfile file 2G 0 B -2PRIO优先级为-2是正常的因为系统默认 swap 分区的优先级是-1而 swapfile 的优先级默认更低以确保在有多个 swap 源时内核会优先使用性能更好的 swap 分区。如果你看到USED列为0B不要慌这恰恰说明一切正常——swap 是按需使用的只有当物理内存真正紧张时内核才会开始往 swap 里写数据。你可以用sudo free -h再次确认Swap行的total应该显示2.0G。一个常见的验证误区是用户启用后立刻free -h看到used是0B就以为没生效。其实free显示的used是当前已使用的 swap 量不是启用状态。只要total不为0就证明已成功启用。另一个更底层的验证方法是查看/proc/swapscat /proc/swaps输出应包含/swapfile的一行记录type为filesize为2097148即 2GB 的 KB 数。这个文件是内核维护的实时 swap 状态映射比swapon --show更权威。4. 持久化配置fstab 的语法陷阱与挂载时机的致命细节临时启用 swap 只是第一步真正的挑战在于让它在每次系统重启后自动生效。这依赖于/etc/fstab文件的正确配置。标准写法是echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab这行命令将一条新的挂载条目追加到 fstab 末尾。让我们逐字段解析其含义/swapfile要挂载的源即我们创建的文件路径。none挂载点。swap 不是挂载到某个目录而是由内核直接管理所以这里必须写none不能写/swap或其他路径。写错会导致mount -a报错unknown filesystem type none。swap文件系统类型。这是固定关键字告诉mount命令这是一个 swap 区域而非 ext4 或 xfs。sw挂载选项options。sw是swap的简写等价于defaults表示启用 swap 的所有默认行为。你也可以写得更明确defaults但sw是约定俗成的写法。0dump 字段。表示该设备不需要被dump命令备份固定为0。0pass 字段。表示该设备在fsck启动检查时的检查顺序。0表示不检查因为 swap 不是常规文件系统fsck对它无效。如果这里误写为1或2系统启动时fsck会尝试检查 swapfile导致启动卡死或报错。提示在编辑/etc/fstab前强烈建议先备份sudo cp /etc/fstab /etc/fstab.backup。fstab 是系统启动的关键文件一个语法错误可能导致系统无法进入图形界面只能通过 recovery mode 修复。然而fstab 的写法只是“表面功夫”真正决定 swap 是否能开机自启的是挂载时机。Ubuntu 18.04 使用 systemd而 swap 的启用是由systemd-swap-generator这个生成器在 early boot 阶段动态生成的 service unit 来完成的。这个生成器会扫描 fstab为每一个swap类型的条目生成一个dev-sda1.swap或swapfile.swap这样的单元。但这里有一个致命细节如果 swapfile 位于一个非根分区例如/home/swapfile而该分区的挂载依赖于local-fs.target那么 swap 的启用服务就会和该分区的挂载服务产生循环依赖。结果就是系统启动时swapfile.swap服务会超时失败swap 无法启用。解决方案有两个一是坚持把 swapfile 放在/分区下最稳妥二是如果必须放/home则需要手动创建一个 systemd drop-in 文件强制swapfile.swap在home.mount之后启动。但这已超出本文的“基础可靠”范畴。所以我的实操心得是永远把 swapfile 放在/下哪怕/剩余空间只有 1GB也优先清理日志和缓存而不是冒险放到/home。因为/分区的挂载是initrd阶段就完成的绝对早于任何用户空间服务swapfile 的路径在此时一定是可访问的。5. 性能调优与深度验证swappiness、vfs_cache_pressure 与真实压力测试swapfile 启用后系统并不会立刻开始使用它。Linux 内核有一套精妙的内存回收策略其核心参数是swappiness。它的取值范围是 0–100默认值为 60。这个数字的含义是“当系统需要回收内存时内核倾向于将多少比例的页面从匿名页anonymous pages即进程堆栈换出到 swap而不是从 page cache文件缓存中回收”。数值越高内核越激进地使用 swap数值越低内核越倾向于保留匿名页优先丢弃文件缓存。对于桌面用户swappiness10是一个广受推荐的平衡值它允许在内存真正吃紧时启用 swap但又不会让 Chrome 这类内存大户刚开几个标签就疯狂往 swap 写数据从而避免 I/O 瓶颈。设置方法很简单echo vm.swappiness10 | sudo tee -a /etc/sysctl.conf sudo sysctl -psysctl -p会立即从/etc/sysctl.conf加载新配置。你可以用cat /proc/sys/vm/swappiness验证是否生效。另一个常被忽视的关联参数是vfs_cache_pressure默认值为 100。它控制内核回收 dentry 和 inode cache目录项和索引节点缓存的积极程度。值越高回收越积极。在 swap 启用后如果swappiness被设得很低如 10而vfs_cache_pressure仍为 100内核可能会过度回收文件缓存导致频繁的磁盘读取反而拖慢系统。一个经验性的配对调优是swappiness10时将vfs_cache_pressure设为50以保持文件缓存的稳定性。命令如下echo vm.vfs_cache_pressure50 | sudo tee -a /etc/sysctl.conf sudo sysctl -p注意swappiness和vfs_cache_pressure都是运行时参数sysctl -p加载后立即生效无需重启。但它们只影响未来的行为不会改变当前已有的内存状态。真正的验证必须来自压力测试。我常用的三步法是基线测量free -h记录当前内存使用sudo iostat -x 1开启磁盘 I/O 实时监控。施加压力运行stress-ng --vm 2 --vm-bytes 4G --timeout 60s。这个命令会启动 2 个进程每个进程申请并锁定 4GB 内存持续 60 秒。它会逼迫内核启动完整的内存回收流程。观察反应在iostat输出中关注%util设备利用率和r/s,w/s读写次数。如果 swapfile 启用正确你会看到w/s显著上升%util接近 100%同时free -h中Swap used会从0B缓慢爬升到几百 MB。如果w/s为 0Swap used始终为0B说明 swap 未被使用可能是swappiness设得太低或是压力还不够大。我曾在一个客户现场遇到过一个诡异问题swapon --show显示 swap 已启用free -h也显示total正确但stress-ng测试时 swap 用量始终为 0。排查发现客户的/etc/sysctl.conf里有一行vm.swappiness0这是 Ubuntu 18.04 某些云镜像的默认配置意在“禁用 swap”。swappiness0并非完全禁用而是让内核只在内存耗尽到最后一刻OOM 边缘才考虑 swap这在stress-ng的 60 秒测试窗口内根本来不及触发。将swappiness改为10后问题立刻解决。这个案例再次印证swap 的启用只是起点调优才是让它真正发挥作用的关键。6. 常见问题速查与独家避坑指南那些文档里不会写的实战教训在过去的三年里我为超过 200 台 Ubuntu 18.04 机器配置过 swap总结出以下高频问题与独家解决方案。这些问题大多源于对 Linux 内存管理机制的误解或是对 Ubuntu 18.04 特定行为的不熟悉。6.1 问题swapon: /swapfile: swapon failed: Invalid argument现象执行sudo swapon /swapfile时报此错误且dmesg | tail显示swapon: swapfile has holes。原因fallocate在某些文件系统如 XFS上如果启用了allocsize选项或存在特定的挂载参数有时会创建出带有“空洞”holes的文件。内核要求 swapfile 必须是连续的、无空洞的块设备映射否则拒绝加载。解决方案放弃fallocate改用dd重新创建sudo swapoff /swapfile sudo rm /swapfile sudo dd if/dev/zero of/swapfile bs1M count2048 statusprogress sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfilebs1M count2048等价于 2GBdd生成的文件是物理连续的绝无空洞。6.2 问题系统重启后 swap 消失free -h显示Swap: 0B现象fstab 已正确配置但每次重启后 swap 都不生效。排查链路第一步sudo systemctl list-units --typeswap检查是否有swapfile.swap这个单元且状态为loaded active。如果没有说明 fstab 条目未被 systemd 识别。第二步sudo systemctl status swapfile.swap查看详细日志。最常见的错误是Failed to activate swap /swapfile: Device or resource busy这通常是因为/swapfile路径所在的文件系统尚未挂载完成。第三步sudo journalctl -u swapfile.swap -n 50 --no-pager查看启动时的具体报错。终极解决方案在 fstab 条目末尾添加nofail选项使其变为/swapfile none swap sw,nofail 0 0nofail告诉 systemd即使这个 swap 启用失败也不要阻塞整个启动过程。更重要的是它会让 systemd 在所有文件系统挂载完成后再尝试一次启用 swap从而规避了挂载时机问题。这是 Ubuntu 18.04 社区公认的、最可靠的 fstab 选项。6.3 问题swapon成功但free -h中used始终为0B怀疑 swap 未工作真相这是完全正常的现象。swap 是懒加载lazy-loaded的内核只在物理内存真正不足、且满足swappiness触发条件时才会开始将匿名页换出。free -h的used列显示的是当前已换出的页面总量不是启用状态。验证方法方法一cat /proc/swaps只要输出中有/swapfile且typefile就证明已启用。方法二sudo vmstat 1 5观察siswap in和soswap out列。在内存压力下so会大于 0。方法三sudo smaps | awk /^Size:/ {sum$2} /^MMUPageSize:/ {if($24) {print 4KB pages:, sum; sum0}}这个命令能粗略估算当前有多少内存页被标记为可换出。6.4 问题在外挂硬盘如 NTFS上创建 swapfile 失败现象fallocate报Operation not supporteddd虽然成功但mkswap后swapon报swapon: /mnt/usb/swapfile: swapon failed: Invalid argument。根本原因NTFS 文件系统不支持 Linux swap 所需的底层特性如直接块映射和原子写入。内核无法保证对 NTFS 上文件的 swap 操作是安全和一致的。结论绝对不要在外挂的 NTFS/exFAT 硬盘上创建 swapfile。这是 Linux 内核的硬性限制不是配置问题。如果你确实需要更大容量的 swap唯一合规的方案是将外挂硬盘格式化为 ext4会清空数据然后将其挂载到/mnt/data再在该挂载点下创建 swapfile。命令如下# 假设硬盘设备是 /dev/sdb1 sudo mkfs.ext4 /dev/sdb1 sudo mkdir -p /mnt/data echo /dev/sdb1 /mnt/data ext4 defaults 0 2 | sudo tee -a /etc/fstab sudo mount -a sudo fallocate -l 4G /mnt/data/swapfile sudo chmod 600 /mnt/data/swapfile sudo mkswap /mnt/data/swapfile echo /mnt/data/swapfile none swap sw,nofail 0 0 | sudo tee -a /etc/fstab sudo swapon /mnt/data/swapfile这个流程虽然稍长但它是唯一能让你在外挂硬盘上安全使用 swap 的方法。记住swap 的可靠性永远排在容量之前。7. 进阶思考swapfile 的生命周期管理与未来演进swapfile 并非一劳永逸的静态配置它有自己的生命周期需要定期审视和维护。我习惯在每季度的系统健康检查中执行以下三个动作第一容量审计。运行sudo swapon --show和sudo free -h对比total和历史峰值used。如果过去三个月里used最高只到512M而你配置了2G说明 swap 过大可以安全缩减。缩减命令是sudo swapoff /swapfile sudo fallocate -l 1G /swapfile sudo mkswap /swapfile sudo swapon /swapfile注意fallocate -l 1G会将文件逻辑大小调整为 1GBmkswap会重写头swapon会重新加载。整个过程无需重启且对正在运行的服务无感知。第二碎片检查。虽然 ext4 对小文件的碎片不敏感但 swapfile 是一个大文件长期使用后可能出现碎片。用filefrag -v /swapfile可以查看其物理块分布。如果extents连续块数量远大于1比如显示128 extents说明文件已严重碎片化。此时最佳实践是停用、删除、重建sudo swapoff /swapfile sudo rm /swapfile sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile重建后的 swapfile 一定是连续的性能最优。第三内核升级适配。Ubuntu 18.04 的内核更新如从 4.15.0-xx 升级到 4.15.0-yy通常不会影响 swapfile但如果你计划升级到更高版本的内核如通过 UKUU 安装 5.x需要留意较新的内核对 swapfile 的校验更严格可能会拒绝加载旧版mkswap创建的文件。此时只需重新执行sudo mkswap /swapfile即可无需更改文件内容。最后关于 swap 的未来Zswap 和 Zram 是两个值得关注的方向。Zram 是一个在 RAM 中创建压缩块设备的技术它把 swap 数据先压缩再存入内存速度比磁盘 swap 快几个数量级特别适合内存充足≥16GB但追求极致响应的场景。而 Zswap 则是一个前端缓存它拦截即将写入磁盘 swap 的数据先尝试在 RAM 中压缩缓存命中则免去磁盘 I/O。Ubuntu 18.04 原生支持 Zram启用只需一条命令sudo apt install zram-config。但在我经手的所有生产案例中95% 的场景一个配置得当的传统 swapfile 依然是最稳定、最透明、最易排障的选择。新技术固然炫酷但老司机的座右铭是能用swapon解决的问题绝不轻易引入zram。因为简单就是最高级的可靠。