首页 / 资讯中心 / 文章详情

Ubuntu磁盘分区扩容与固定Swap内存配置全攻略

Ubuntu磁盘分区扩容与固定Swap内存配置全攻略 ★ FEATURED ARTICLE
很多人第一次看到“扩容ubuntu 固定内存”这个标题第一反应是给机器重新插一根物理内存条。但真跑到服务器或者自己常用的Ubuntu工作站上一看90%的场景根本不是物理插槽不够而是系统把磁盘空间、交换分区和内存策略混在一起导致程序一跑多就OOMOut Of Memory或者开机后磁盘被日志和缓存写满系统直接卡死。我自己这几年在给团队维护Ubuntu服务器和个人开发机时没少碰这种“说扩容又不是真扩容”的需求。本文就把这套操作完整捋一遍从磁盘分区扩容到设置固定大小的swap文件再到调整内核内存参数最后附上我在实际环境里踩过的坑。适合正在被“内存不足”提示折磨的开发者、运维新手以及所有想在Ubuntu上把内存使用变得可控、可预期的朋友。1. 先搞清楚“扩容”和“固定内存”到底是指什么1.1 先判断你遇到的是哪一类内存问题拿到一台Ubuntu机器第一步不是急着执行命令而是搞清楚“内存不够”到底是什么症状。我在实际排查中通常把问题分成三类每一类的处理方式完全不同第一类是“可用内存看着很少”。输入free -h发现used很高free很低但机器其实不卡。这种情况多半是Linux的page cache机制在起作用缓存了读写过的文件内容目的是加快后续访问。这时候你以为内存不够实际上系统随时可以回收这部分缓存供程序使用。解决方向是理解并调整缓存回收策略而不是简单加swap。第二类是“程序一启动就被杀”。比如跑编译、起Docker容器、加载大型模型系统直接报Killed或Cannot allocate memory。这是真正的物理内存或swap耗尽需要扩容总可用内存也就是给系统增加swap空间或者调整进程的内存占用上限。第三类是“磁盘满了导致无法扩容”。swap文件需要写在磁盘上如果根分区几乎满了你再怎么想扩swap都白搭。这种情况先要清理系统盘或者把现有物理分区扩大才能谈下一步。所以“扩容ubuntu 固定内存”这个标题拆开来看其实是两件事一是给磁盘分区扩容腾出空间二是把swap虚拟内存配置成固定大小让系统总内存变得可预期。两者一起做才能解决“内存看着不够用”的根本问题。1.2 为什么“固定大小”比“自动浮动”更靠谱很多新手喜欢用zram或者系统默认的动态swap策略这样虽然能临时缓解内存压力但有个很尴尬的问题你不知道系统什么时候会突然吃掉大量交换空间导致其它需要内存的进程跟着遭殃。比如我在某公司帮同事调试一台8G内存的Ubuntu笔记本系统默认用了swapfile加swappiness60平时好好的一开浏览器再加个IDE内存就疯狂写swap结果整个桌面操作卡成PPT。固定大小的核心思路是提前把交换空间规划成确定值比如物理内存的1到2倍然后用sysctl控制内核在什么阈值下才启用交换。这样做的好处是对应用层透明、性能可预期排查问题时也只需要看几个固定参数不用猜系统是不是又在动态调整。再加上swap文件本身可以随时调整大小比挤压物理分区灵活得多适合绝大多数个人开发机和中小型服务器。2. 磁盘分区层面的扩容准备2.1 查看当前磁盘和分区状态的标准姿势在动任何手脚之前先收集系统当前状态。我习惯按下面三条命令依次执行顺序基本固定free -h df -h lsblkfree -h看的是实时内存和swap使用量df -h确认每个挂载点的磁盘占用率lsblk则用来查看块设备的分区拓扑。举个例子如果df -h显示/dev/sda2挂在根目录且使用率92%而lsblk又显示sda2后面还有一大块未分配空间那就说明这块虚拟磁盘在创建时没把容量全部分给系统扩容的第一步就是把这个未使用的间隙变成可用分区。这里有个很容易看漏的细节如果机器用的是LVM逻辑卷lsblk看到的分区结构和普通物理分区不一样你需要再用sudo pvs、sudo vgs、sudo lvs单独确认逻辑卷的信息。我曾经接手过一台某团队的机器所有人都只看lsblk以为分区满了就没法扩实际上底层LVM卷组还有几十G空闲最后两条命令就解决了问题。2.2 根分区空间不够时的三种处理思路根分区满了在Ubuntu上通常有三种思路按推荐程度排序第一种是直接扩展已有物理分区。这要求分区后面还有空闲扇区且文件系统支持在线扩容。对现代Ubuntu默认的ext4或xfs可以用growpart配合resize2fs或xfs_growfs实现。比如把/dev/sda2扩展到使用磁盘剩余全部空间sudo growpart /dev/sda 2 sudo resize2fs /dev/sda2growpart的2是分区编号不是大小。如果磁盘本身已扩容但分区没识别可以先用sudo partprobe或重启让内核重新读取分区表。第二种是新建一个分区并挂载到新目录。比如数据目录/data原本在根分区里你可以把新分区挂到/data把旧数据挪过去。这种方式更安全不影响系统分区适合长期存放日志、Docker数据、数据库文件等大文件。第三种是清理系统内的大文件不新增磁盘操作。sudo journalctl --vacuum-time7d清掉七天前的日志sudo apt clean清理包缓存sudo du -h --max-depth1 /逐层看哪个目录吃掉了磁盘。很多机器其实只是被日志和缓存堆满了根本没有扩容的必要。注意千万不要在分区挂载状态下直接删除或移动/dev/sda这类块设备文件那不是普通文件操作不当会让文件系统损坏。3. 用swap文件设置固定大小虚拟内存3.1 为什么选择swap文件而不是swap分区Linux支持两种swap承载方式独立分区和文件。分区方式需要提前规划磁盘布局一旦创建后要再改大小就很麻烦而且很多云主机在创建时根本没有划分swap分区。swap文件的优势是随时创建、随时删掉、大小随便改对个人开发机和大部分中小型服务器来说灵活度远高于分区。另一个好处是便于“固定化”。通过/etc/fstab固定挂载项和sysctl.conf固定交换策略就能保证每次开机都自动使用你设定的大小和优先级。我自己生产环境里也这么用配合systemd服务监控swap文件跑几个月都不会出问题。3.2 创建swap文件的完整命令与参数说明下面是创建8G swap文件的完整流程我建议用dd而不是fallocate。原因后面细说先看命令sudo dd if/dev/zero of/swapfile bs1M count8192 statusprogress sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile逐条解释dd if/dev/zero of/swapfile bs1M count8192从/dev/zero读取零字节写入/swapfile块大小1M共写8192块。count8192就是8G。别随意调大bs某些文件系统对块大小的兼容性会出问题。statusprogress能在慢慢写入时显示进度否则会让人以为卡住了。chmod 600swap文件只允许root读写。如果不做这一步swapon会提示insecure permissions并拒绝启用。mkswap把文件格式化成swap文件系统相当于给这个文件打上“我是交换空间”的标记。swapon立即启用这个交换文件不需要重启。如果系统内存只有4G建议先建4G或6G如果是16G内存的开发机swap可以设16G这样休眠hibernate时的镜像也能放下。总的原则是统计型任务多、内存占用峰值稳定的机器swap设为物理内存的0.5到1倍就够负载波动大的机器1到2倍更稳。3.3 开机自动挂载与何时用UUID启用swap后如果直接重启swap会不见因为系统还不知道要自动加载它。用下面命令把它写入/etc/fstabecho /swapfile none swap sw 0 0 | sudo tee -a /etc/fstabnone表示没有挂载点swap是文件系统类型sw是挂载参数0 0表示不需要备份和开机自检。如果是普通的数据分区我会建议用UUID避免设备名变动问题但swap文件是直接写路径不存在设备顺序漂移的问题所以直接写路径即可。然后确认开机设置和当前状态sudo sysctl --system swapon --show如果swapon --show能看到路径和大小说明当前已生效/etc/fstab里的配置会在下次开机时接管。以后再想调整大小流程就变成先sudo swapoff /swapfile删除旧文件重新按新大小创建再次swapon不用动fstab。4. 调整系统内存策略让“固定”真正落地4.1 swappiness参数换出与换入的频率控制只有swap文件还不够Linux内核默认的交换倾向可能不符合你的使用场景。控制这个行为的关键参数叫vm.swappiness取值范围0到100值越大越积极使用swap值越小越倾向于使用物理内存。Ubuntu桌面版默认值是60这对小内存机器公平但对大内存机器来说太激进。我自己的经验是内存8G及以下的桌面机器保持默认或设为20避免物理内存还有余量时系统就开始换出进程。内存16G以上的开发机和服务器设为10尽量把内存留给应用层缓存。极端场景如数据库服务器设成0或1让内核几乎不主动swap宁可让应用层慢一点也不让进程被杀。持久化修改方法是在/etc/sysctl.conf里加一行vm.swappiness10保存后执行sudo sysctl -p立即生效。配合前面创建的固定大小swap文件“固定内存”的目标就已经实现大半了可用总内存固定、交换倾向固定、系统行为可预期。4.2 缓存压力与OOM风险控制另一个常被忽略的参数是vm.vfs_cache_pressure默认100表示内核回收目录项和inode缓存的压力。数字越大回收越快数字越小越倾向保留缓存。对编译频繁、跑容器多的机器把它调到50到80能明显减少小文件操作的卡顿。补充一个OOM风险控制技巧如果某个进程频繁导致整机内存耗尽可以在systemd服务文件里加上MemoryMax限制。比如JVM的堆占用不稳定可以在启动脚本前用systemd-run --scope -p MemoryMax8G -- your_command临时限定进程内存防止它把swap和物理内存全部吃光。这种方法在排查“某进程一动就杀全盘”的故障时非常有用我处理过几次Docker容器内存泄漏问题都是先用这种方式把影响范围框住再定位。5. 我踩过的坑swap与分区扩容的典型问题速查5.1 swap文件明明创建了为什么启用失败这个问题我遇到不止一次而且报错原因各不相同。整理成一张速查表现象常见原因处理方法swapon: /swapfile: insecure permissions文件权限不是600chmod 600 /swapfile后重试swapon: /swapfile: swapon failed: Invalid argument文件系统不支持或用了fallocate产生空洞改用dd重建swap文件swapon: /swapfile: read swap header failed没执行mkswap补执行sudo mkswap /swapfile开机后swap不存在/etc/fstab写错或没写检查fstab内容确保路径和参数正确特别说一下fallocate。它创建文件很快但在某些文件系统比如旧版ext4上会生成带空洞的稀疏文件swap需要的是连续真实块结果就会出现“明明文件大小对但swapon失败”的情况。保险起见我后来统一改用dd虽然写入慢一点但一次成功。5.2 root分区没有空闲空间swap文件没地方放这是最尴尬的场景你检查完才发现根分区已经用到90%以上建不了大swap文件。处理顺序我建议这样先清日志和软件包缓存看能释放多少空间。如果仍然不足找一个剩余空间最大的挂载点比如/home或/data把swap文件建在那里。修改/etc/fstab使用绝对路径比如/data/swapfile。要注意的是如果目标分区是通过noexec或nodev选项挂载的swap可能无法启用。用mount -o remount,exec,dev /data可以临时调整但更稳妥的长期方案是单独建一个小分区专门放swap。5.3 修改fstab后开机进入紧急模式改完/etc/fstab重启结果卡在emergency mode这是很多新手最慌的时刻。其实解决很简单在提示符下输入root密码执行vi /etc/fstab把刚才加错的那行注释掉或改正然后reboot就恢复了。因为fstab里一行错误配置导致无法通过自检系统不会冒险继续挂载宁可卡住等你修复这是保护机制不要慌。避免的办法是每次改fstab前先备份sudo cp /etc/fstab /etc/fstab.bak.$(date %F)改完后可以用sudo mount -a先测试所有条目是否能正确挂载没问题再重启。5.4 内存扩容后程序仍然报内存不足swap有了物理内存也有余量程序却仍然报Cannot allocate memory这时候要怀疑的是进程本身被限制了。先查ulimit -a如果max memory size或virtual memory出现过小值可以通过ulimit -v unlimited临时解除。持久化可以在/etc/security/limits.conf里给指定用户设置。另一个隐蔽原因是overcommit_memory参数。执行cat /proc/sys/vm/overcommit_memory如果显示2表示内核启用了严格的内存超卖控制此时即使有swap也可能拒绝分配内存改为sudo sysctl vm.overcommit_memory0通常就能解决。这个参数平时没人动但一旦碰到“明明内存没满却申请不到内存”的诡异问题十有八九是它。6. 进阶玩法把“扩容”扩到应用层面6.1 容器和Java进程的内存限定前面讲的都是操作系统层面的事情但实际开发中很多“内存不够”的元凶是单个应用无限制地吃内存。Java的JVM默认会根据宿主机内存计算堆大小一台32G机器上的Java进程起步就能拿8G堆两个服务一跑内存就紧张了。对此最有效的“固定内存”手段是在启动命令上加显式参数java -Xms2G -Xmx4G -jar your-app.jarDocker容器则用--memory和--memory-swap控制硬上限docker run --memory4g --memory-swap6g your-image--memory4g限制物理内存上限--memory-swap6g表示允许最多额外使用2G交换。这类配置应该写进调度文件或服务配置文件而不是每次手工指定否则重启一次丢一次迟早又爆掉。6.2 如何验证扩容效果而不是“感觉不卡了”所有配置做完别急着收工。我用一套固定流程验证free -h swapon --show cat /proc/sys/vm/swappiness三个输出确认当前交换空间是预期大小、策略参数已生效。然后压一下内存stress-ng --vm 2 --vm-bytes 4G --timeout 30s或者直接启动一个吃内存的应用观察free -h里swap数值是否逐渐上升系统是否还能正常响应。如果swap没有变化说明当前负载还没到需要交换的程度如果变化太快说明swappiness可能调得太激进需要再衰减。6.3 不止Ubuntu这套思路迁移到Debian和树莓派系统最后说一个额外价值这套操作不仅适用于UbuntuDebian系的所有发行版、树莓派的官方系统、以及各类基于Ubuntu的衍生发行版命令几乎完全一致。区别只在于某些云厂商镜像预置了奇怪的swap分区配置这时候需要先删除旧的swap配置再重建。判断方法还是回到第一条free -h和swapon --show看清现状再动手。写在最后做系统资源调整最忌讳的就是“敲完命令就以为完事”。配置固定swap和内存策略归根到底是给系统一个明确的边界让它在负载波动时仍然有可预期的行为。我个人的习惯是不管机器内存多大都保留一份与物理内存等大的swap文件并把swappiness压到10左右。这样既能兜底突发峰值又不会让系统在日常轻负载下无谓写盘。如果你也一直在为Ubuntu内存不足头疼照着上面这套流程走一遍大部分问题都能在当前系统层面解决而不是只能灰心去插内存条。
阅读完成 · 觉得有帮助?
咨询建站