Ubuntu 的 RAM 很快用完,我的计算机开始死机。什么命令可以解决这个问题?

Ano*_*non 74 command-line swap freeze ram

当我在后台编译软件时,它经常发生在我身上,突然一切都开始变慢并最终冻结 [如果我什么都不做],因为我的 RAM 和交换空间都用完了。

这个问题假设我有足够的时间和资源来打开 Gnome 终端,搜索我的历史记录并执行一个sudo命令。

什么命令可以让我免于硬重启,或者根本不需要重启?

Oli*_*Oli 84

根据我的经验,Firefox 和 Chrome 使用的 RAM 比我前 7 台计算机的总和还要多。可能不止这些,但我正在偏离我的观点。您应该做的第一件事是关闭浏览器。命令?

killall -9 firefox google-chrome google-chrome-stable chromium-browser
Run Code Online (Sandbox Code Playgroud)

我已经将最流行的浏览器绑定到一个命令中,但很明显,如果您正在运行其他东西(或者知道您没有使用其中之一),只需修改该命令即可。这killall -9 ...是重要的一点。人们确实对SIGKILL(信号编号 9)持怀疑态度,但浏览器具有极强的弹性。更重要的是,通过缓慢终止SIGTERM将意味着浏览器会进行大量垃圾清理工作——这需要额外的 RAM 突发——而在这种情况下,这是你无法承受的。

如果您无法将其放入已运行的终端或Alt+F2对话中,请考虑切换到 TTY。Control+ Alt+F2会让你进入 TTY2,它应该允许你登录(虽然它可能很慢),甚至应该让你使用类似的东西htop来调试问题。我认为我从来没有用完 RAM 到无法起床的地步htop

长期解决方案包括购买更多 RAM,通过远程计算机租用它,或者不做您当前正在做的事情。我将把复杂的经济论据留给你,但一般来说,RAM 的购买价格便宜,但如果你只需要一个突发量,按分钟或小时计费的 VPS 服务器是一个不错的选择。

  • 购买内存...为什么不下载更多内存? (2认同)

Muz*_*zer 66

在启用了 Magic System Request Key 的系统上,按Alt + System Request+ f(如果没有在键盘上标记,System Request通常是在Print Screen键上)将手动调用内核的内存不足杀手 (oomkiller),它会尝试选择最严重的违规进程内存使用并杀死它。如果您的时间可能比您描述的要少,并且系统即将开始(或者可能已经开始)颠簸,您可以执行此操作 - 在这种情况下,您可能并不关心究竟是什么被杀死,只是您结束了建立一个可用的系统。有时这最终会杀死 X,但如今大多数情况下,它在选择一个坏进程方面比过去要好得多。

  • @T.Sar 如果您使用的是健全的构建系统,您就不会失去进展。您将保留除实际编译的目标文件之外的所有目标文件,然后您几乎可以回到上次中断的地方。 (9认同)
  • @T.Sar Linux 从编译器的 POV 来看并不复杂。实际上几乎没有任何 C 程序。C++ 呢?您是否尝试过使用 Eigen 或 Boost 构建程序?您会惊讶于编译器有时会在此类程序中占用多少内存——而且它们本身不必很复杂。 (7认同)
  • @T.Sar 如果你要直接摔跤,你要么输了,要么有机会杀死记忆吞噬者。如果你只是不表演,你就不会得到任何东西。 (5认同)
  • @Muzer 这仅在您将 `kernel.sysrq` 设置为 `1` 或在 `/etc/sysctl.d/10-magic-sysrq.conf` 中包含正确位的数字时才有效。 (4认同)
  • @T.Sar 仅仅因为你编译的东西不健全并不意味着构建系统不健全。自远古以来,构建系统就存储了目标文件,以便在后续编译中重复使用。另一方面,我当然可以说出许多软件项目比 Linux(它通常设计得很好)更不理智。例如,使用 8 个并行构建线程编译 Firefox 或 OpenOffice 之类的东西,我可以很容易地看到它占用了 GB 级的 RAM。还有许多依赖于数百个库的整体企业系统。 (3认同)
  • 如果您的内存耗尽,这是一个非常糟糕的主意,因为您正在编译非常复杂的东西。有一个非常重要的机会杀死你的编译器并失去你到目前为止的所有进度,这在一个非常大的项目中可能是一个大问题。 (2认同)
  • @T.Sar 我不知道,如果您正在进行并行构建并且文件具有相当复杂的相互依赖性,我可以看到它消耗了大量内存。再加上通常会占用大量内存的电子邮件客户端和打开多个选项卡的 Web 浏览器,我可以看到它确实推动了较弱的系统。 (2认同)
  • @T.Sar “在 Windows 7 中,插入一个配置了 TurboBoost 的闪存驱动器可以让你免于 OOM 问题”......我认为你是指 ReadyBoost,而不是 TurboBoost(TurboBoost 是一种 CPU 频率自适应技术)。ReadyBoost 在 OOM 情况下无济于事——它提供额外的磁盘缓存,而不是额外的虚拟内存。 (2认同)
  • @T.Sar *Linux 本身* 只有 2 到 10 MB 的编译代码,按照今天的标准,它几乎不是一个复杂的软件。 (2认同)
  • @wizzwizz4:嗯,这就是 *nix 的重点,几乎所有“系统”都是小的独立部分。此外,软件的复杂性和内存使用与编译的复杂性并没有那么密切相关。我曾开发过可以使用数百 GB 并运行数天进行一些相当复杂的计算的并行应用程序,但它们可以在几分钟内编译,而不会在 2 GB 笔记本电脑上超载内存。 (2认同)

Sco*_*der 20

与其他答案相反,我建议您在执行此操作时禁用交换。虽然交换使您的系统以可预测的方式运行,并且通常用于增加访问磁盘的应用程序的吞吐量(通过驱逐未使用的页面为磁盘缓存留出空间),但在这种情况下,听起来您的系统正在变慢到无法使用的级别,因为过多的主动使用的内存被强行逐出以进行交换。

我建议在执行此任务时完全禁用交换,以便内存不足的杀手会在 RAM 填满时立即采取行动。

替代解决方案:

  • 通过将交换分区放在 RAID1 中来提高交换的读取速度
    • 或者 RAID0,如果您觉得有风险,但如果您的任何磁盘出现故障,这将导致大量正在运行的程序。
  • 减少并发构建作业的数量(“更多内核 = 更高速度”,我们都说,忘记了它会对 RAM 造成线性损失)
  • 这可以双向进行,但请尝试zswap在内核中启用。这会在页面被发送到交换之前压缩页面,这可能会提供足够的摆动空间来加速您的机器。另一方面,它最终可能会成为额外压缩/解压的障碍。
  • 拒绝优化或使用不同的编译器。优化代码有时会占用数 GB 的内存。如果您打开了 LTO,您也将在链接阶段使用大量 RAM。如果所有其他方法都失败了,您可以尝试使用更轻量级的编译器(例如tcc)编译您的项目,代价是编译产品的运行时性能会受到轻微影响。(如果您出于开发/调试目的这样做,这通常是可以接受的。)

  • @Akiva 你试过没有交换吗?这个答案是准确的。我想补充一点,当您已经处于绑定状态时,运行 ``sudo swapoff -a`` 可能会节省您的时间:它将立即停止对交换空间的任何额外使用,即应该在下一个瞬间调用 OOM 杀手,并且使机器进入工作状态。``sudo swapoff -a`` 在调试内存泄漏或编译(例如,firefox)时也是一个很好的预防措施。通常,交换有点用(例如用于休眠或交换出真正不需要的东西),但是当您实际使用内存时,冻结会更糟。 (10认同)
  • 如果您关闭了交换,这就是当您耗尽内存时 Linux 的行为。如果 Linux 没有调用内存不足杀手而是冻结,这可能意味着设置存在更深层次的问题。当然,如果打开了交换,则行为会略有不同。 (6认同)
  • @Score_Under:每个磁盘上的单独交换分区应该比 md raid0 设备上的交换更有效。我忘了我在哪里读到的。[Linux RAID wiki 建议在raid0 上使用单独的分区,但并没有说明为什么它更好](https://raid.wiki.kernel.org/index.php/Why_RAID%3F#Swapping_on_RAID)。无论如何,是的,RAID1 或 RAID10n2 对交换很有意义,特别是如果您主要只是希望能够交换一些脏但非常冷的页面,以便为页面缓存留下更多 RAM。即交换性能不是什么大问题。 (2认同)
  • 我的观点是,按照您的建议,人们可能根本无法运行这些程序,因为它们需要交换。一个 100% 失败的构建比一个有 50% 机会锁定系统的构建更糟糕,不是吗? (2认同)
  • 没有交换,在许多机器上不可能编译大块代码。为什么你会认为这是他想要牺牲的编译? (2认同)
  • @DavidSchwartz 有时人们会惊讶于一个进程需要如此大量的内存。一旦知道了(并且最好以理智的方式找出来,即崩溃编译而不完全锁定计算机,可能会以这种方式丢失其他进程中的有价值数据),就可以释放更多内存,例如通过在编译过程中以受控方式关闭浏览器、邮件客户端和其他与编译器无关的软件。使用交换和糟糕的 I/O 调度,你得到的只是你不太可能从中恢复的冻结。 (2认同)

Goh*_*ohu 14

您可以使用以下命令(如果需要可重复)使用系统上最多的 RAM 终止进程:

ps -eo pid --no-headers --sort=-%mem | head -1 | xargs kill -9
Run Code Online (Sandbox Code Playgroud)

和:

  • ps -eo pid --no-headers --sort=-%mem: 显示所有正在运行的进程的进程 id,按内存使用情况排序
  • head -1: 只保留第一行(使用最多内存的进程)
  • xargs kill -9: 终止进程

在德米特里的准确评论后编辑:

这是一个快速而肮脏的解决方案,应该在没有运行敏感任务(您不想要的任务kill -9)时执行。

  • 这比让 OOM 杀手处理情况要糟糕得多。OOM 杀手比这要聪明得多。您真的会在正在进行编译的计算机上运行这些命令吗? (6认同)

Bas*_*tch 11

在运行消耗资源的命令之前,您还可以使用setrlimit(2)系统调用,可能使用ulimitbash shelllimit内置(或zsh 中的内置),特别是-vfor RLIMIT_AS。然后过大的虚拟地址空间的消耗(例如用MMAP(2)SBRK(2)使用的malloc(3) )将失败(用错误号(3)ENOMEM)。

然后它们(即,在您键入 之后,您的 shell 中的饥饿进程ulimit)将在冻结您的系统之前终止。

另请阅读Linux Ate My RAM并考虑禁用内存过量使用(通过echo 0 > /proc/sys/vm/overcommit_memory 以 root 身份运行命令,请参阅proc(5) ...)。


小智 11

当我在后台编译软件时,这种情况经常发生在我身上

在这种情况下,类似于“killall -9 make”(或者你用来管理你的编译的任何东西,如果不是 make)。这将停止编译继续进行,将 SIGHUP 从它启动的所有编译器进程(希望也使它们停止)并且作为奖励,假设您以登录的用户身份进行编译,则不需要 sudo在作为。而且由于它会杀死问题的实际原因,而不是您的 Web 浏览器、X 会话或随机某个进程,因此它不会干扰您当时在系统上执行的任何其他操作。

  • 很遗憾我不得不向下滚动才能找到这个答案。我希望有人会提出一种方法来暂停这个 RAM 吃者的进展。 (2认同)

小智 9

为自己创造更多的交换。

以下将添加 8G 的交换:

dd if=/dev/zero of=/root/moreswap bs=1M count=8192
mkswap /root/moreswap
swapon /root/moreswap
Run Code Online (Sandbox Code Playgroud)

它仍然会很慢(您正在交换),但您实际上不应该用完。现代版本的 Linux 可以交换文件。现在交换分区的唯一用途是让您的笔记本电脑休眠。

  • 一些交换通常是明智的,但分配大量只是让机器在 OOM 杀手介入并挑选志愿者之前进行更多的振动。关于“双倍你的 ram 作为交换”的古老角色早已不复存在。就个人而言,我认为分配超过 ~1 GB 的交换总量没有任何价值。 (7认同)
  • 使用 ext4,您可以用 `fallocate -l 8G /root/moreswap` 代替 `dd` 以避免在系统抖动时需要执行 8GB 的​​ I/O。但是,这不适用于任何其他文件系统。绝对不是 XFS,其中 swapon 将未写入的范围视为漏洞。(我猜这个 [xfs 邮件列表讨论](http://oss.sgi.com/archives/xfs/2007-06/msg01349.html) 没有成功)。另请参阅 [`swapd`](http://cvs.linux.hr/swapd/),这是一个动态创建/删除交换文件以节省磁盘空间的守护进程。还有 https://askubuntu.com/questions/905668/does-ubuntu-support-dynamic-swap-file-sizing (5认同)

Dmi*_*yev 6

在短时间内获得大量空闲 RAM 的一种方法是使用zram,它创建一个压缩的 RAM 磁盘并在那里交换。对于任何半体面的 CPU,这比常规交换要快得多,并且对于许多现代 RAM 猪(如 Web 浏览器),压缩率非常高。

假设你已经安装并配置了 zram,你所要做的就是运行

sudo service zramswap start
Run Code Online (Sandbox Code Playgroud)