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


73

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

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

什么命令可以使我免于必须进行硬重启或完全重启的麻烦?


评论不作进一步讨论;此对话已转移至聊天
托马斯·沃德

1
如果交换空间用完了,我认为您的交换空间太少了。我在这台计算机上获得了20G的交换空间。关键是要给它足够的时间来使用可用的系统,以杀死占用内存的所有内容。这不是只使用将要使用的东西,而是希望永远不要使用的东西。
JoL

1
您确定RAM和交换都已装满吗?如果是这种情况,OOM处理程序将终止您的编译器并释放内存(并破坏您的构建过程)。否则,我会认为它已被填满,也许您的系统运行缓慢,因为交换位于系统磁盘上。
sudo

3
如果没有足够的RAM支持并行构建,请尝试减少并行构建的数量。如果您的构建开始交换,您将变慢。使用make-j4例如一次尝试4个并行构建。
Shahbaz

1
“ Alexa给我定了8个ram的演出”

Answers:


84

以我的经验,Firefox和Chrome使用的内存比前7台计算机的总和还多。可能还不止这些,但我已经远离了我的观点。您应该做的第一件事就是关闭浏览器。命令吗

killall -9 firefox google-chrome google-chrome-stable chromium-browser

我已经将最流行的浏览器绑定到一个命令中,但是很显然,如果您正在运行其他浏览器(或者知道您未使用其中一种),只需修改该命令即可。该killall -9 ...是重要的一点。人们确实对此感到疑惑SIGKILL(信号号9),但浏览器却非常灵活。更重要的是,缓慢终止SIGTERM会意味着浏览器会产生大量的清理垃圾,这需要大量额外的RAM,而在这种情况下,这是您无法承受的。

如果您无法进入已经运行的终端或Alt+ F2对话框,请考虑切换到TTY。Control+ Alt+ F2将带您进入TTY2,它应该允许您登录(尽管可能很慢),甚至应该允许您使用类似的方法htop来调试问题。我认为我还没有用完RAM,直到无法站htop起来。

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


评论不作进一步讨论;此对话已转移至聊天
托马斯·沃德

我有lazygit不时使用的与自己的命令关联的几个命令,也许可以在此处应用类似的内容?整个killall ...脚本可以简化为一个简单的内容emptyram或类似形式
Francisco Presencia

如果您知道正在运行什么浏览器,则无需运行完整命令,并且我认为大多数可以确定内存不足的人都可以。通过扩展,我发现很难记住我写了一个emptyram脚本,而不仅仅是打入killall -9 firefox
奥利

2
购买RAM ...为什么不下载更多RAM?
Stephan Bijzitter

1
好吧,您可能会开玩笑,但是如果您需要在短时间内做一些事情,而这又需要更多的RAM和CPU,那么一分钟租用VPS对于一次拍摄来说是非常经济的。
奥利

66

在启用了“魔术系统请求键”的系统上,按Alt + System Request+ f(如果未在键盘上标记,System Request通常会在Print Screen键上)将手动调用内核的内存不足杀手(oomkiller),该程序将尝试选择最坏的违规进程。占用内存并杀死它。如果您的时间可能比描述的要少,并且系统即将启动(或可能已经启动)抖动,则可以执行此操作-在这种情况下,您可能并不在乎到底是什么被杀死,而只是终止用一个可用的系统。有时这可能最终导致杀死X,但是如今,大多数时候选择一个错误的过程比过去要好得多。


5
@ T.Sar如果您直接陷入困境,那么您可能已经失去或有机会杀死吞噬内存的人。如果您不采取行动,您将一无所获。
Ruslan

4
@Muzer仅当您将设置kernel.sysrq1或包含正确位的数字时,此功能才起作用/etc/sysctl.d/10-magic-sysrq.conf
Ruslan

9
@ T.Sar如果您使用的是可靠的构建系统,则不会失去进度。您将保留所有的目标文件,但实际上是正在编译的目标文件,然后您将回到几乎停下来的位置。
Muzer

3
@ T.Sar仅仅因为您正在编译的东西不是健全的,并不意味着构建系统也不是健全的。自远古以来的构建系统已存储了目标文件,以供后续编译使用。另一方面,我当然可以说很多软件项目的名称比Linux(通常设计得不错)要少。例如,用8个并行构建线程编译Firefox或OpenOffice之类的东西时,我可以很容易地看到它占用了GB的RAM。还有很多依赖数百个库的整体式公司系统。
Muzer

7
@ T.Sar Linux从编译器的POV来看并不复杂。实际上,几乎没有任何C程序。C ++呢?您是否尝试过使用Eigen或Boost构建程序?您会感到惊讶的是,编译器有时会在此类程序中占用多少内存,并且它们本身不必很复杂。
Ruslan

20

与其他答案相反,我建议您在执行此操作时禁用交换。尽管交换可以使您的系统以可预测的方式运行,并且经常用于提高访问磁盘的应用程序的吞吐量(通过逐出未使用的页面以为磁盘高速缓存留出空间),但在这种情况下,听起来好像您的系统正在减慢速度到无法使用的程度,因为强行驱逐了太多频繁使用的内存以进行交换。

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

替代解决方案:

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

6
如果您已关闭交换功能,这就是Linux在内存不足时的行为。如果Linux不调用内存不足杀手,而是冻结,则可能表示该设置存在更深层次的问题。当然,如果启用交换,则行为会稍有不同。
Score_

10
@Akiva您是否尝试过不交换?这个答案是即时的。我想补充一点,sudo swapoff -a当您已经处于绑定状态时,运行可能会节省您的时间:它将立即停止对交换空间的任何其他使用,即,应在下一个瞬间调用OOM杀手,并使计算机进入工作状态。sudo swapoff -a在调试内存泄漏或编译(例如firefox)时,也是一种极好的预防措施。通常,交换有点有用(例如,用于休眠或交换出真正不需要的东西),但是当您实际使用内存时,冻结会更糟。
JonasSchäfer'17

2
@Score_Under:每个磁盘上的单独交换分区应该比md raid0设备上的交换效率要高得多。我忘了我在哪里读的。 Linux RAID Wiki建议在raid0上使用单独的分区,但是并没有说出什么更好的理由。无论如何,RAID1或RAID10n2对于交换很有意义,尤其是在您只希望能够交换一些脏但很冷的页面以为页面缓存留出更多RAM时。也就是说,交换性能并不重要。
彼得·科德斯

2
我的观点是,按照您的建议,一个程序可能根本无法运行,因为它们需要交换。100%的时间失败的构建比50%的机会锁定系统的构建更糟糕,不是吗?
德米特里·格里戈里耶夫

2
没有交换,在许多机器上就不可能编译大量代码。您为什么会认为这是他要牺牲的编译内容?
David Schwartz

14

您可以使用以下命令(必要时重复进行此操作)以使用系统上最多的RAM终止进程:

ps -eo pid --no-headers --sort=-%mem | head -1 | xargs kill -9

带有:

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

在Dmitry的准确评论后进行编辑:

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


5
这比让OOM杀手处理这种情况要糟糕得多。OOM杀手比这聪明得多。您是否确实在正在进行编译的计算机上运行此类命令?
德米特里·格里戈里耶夫

@DmitryGrigoryev有时候杀死我桌面上的Xorg非常聪明。在现代内核中,OOMK似乎已经变得有些理智了,但是我毕竟并不真正相信它。
Ruslan

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会话或随机的某些进程,因此它不会干扰您当时在系统上所做的任何事情。


2
只可惜我不得不向下滚动才能找到这个答案。我希望有人能提出一种方法来中止此RAM占用器的进度。
TOOGAM

OP期望得到的答案几乎没有,但是它回答了文学上的问题:当我在废纸machine机上构建时,我的废纸machine机变得不可用-停止在废纸machine机上构建。
9ilsdx 9rvj 0lo

9

为自己创建更多交换。

以下将添加8G交换:

dd if=/dev/zero of=/root/moreswap bs=1M count=8192
mkswap /root/moreswap
swapon /root/moreswap

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


1
实际上,在这里,我已经将此方法实现为脚本。对于动态添加交换非常有用。
Sergiy Kolodyazhnyy

7
一般而言,进行一些交换是明智的,但是分配大量资金只会让机器在OOM杀手介入并挑选志愿者之前更加猛烈地跳动。关于“将您的公羊加倍交换”的经验法则的老生常谈已久。我个人认为分配超过约1 GB的交换总量没有任何价值。
Criggie '17

5
ext4的,您可以fallocate -l 8G /root/moreswap代替dd,以避免以往任何时候都需要做的我8GB / O在系统颠簸。但是,这不适用于任何其他文件系统。绝对不是XFS,其中swapon将未写入的扩展视为漏洞。(我想这个xfs邮件列表讨论没有成功)。另请参阅swapd,一个守护进程可以动态创建/删除交换文件以节省磁盘空间。也请参见askubuntu.com/questions/905668/…–
彼得·科德斯

1
@Criggie“就个人而言,我认为分配的总交换量不超过1 GB毫无价值”-您是否尝试构建Firefox?
德米特里·格里戈里耶夫

1
@Akiva上次检查时,建议的构建配置为16 GB RAM。主要的可执行文件(xul.dll)约为50 MB,因此比Linux内核大10倍。
德米特里·格里戈里耶夫

5

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

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

sudo service zramswap start

这对像btrfs这样的所有文件系统都有效吗?
Akiva

1
@Akiva zram永远不会碰磁盘,所以我会说是;)
德米特里·格里戈里耶夫

3

sudo swapoff -a将禁用交换,如果系统内存不足,内核将自动终止得分最高的进程。如果我知道我将要运行大量RAM,并且宁愿杀死它,而不是进入交换状态并永久卡住,我宁愿杀死它,也可以使用它。用于sudo swapon -a以后重新启用它。

稍后,您可能需要查看一下交换设置。听起来您的交换与根分区位于同一磁盘上,当您按交换时,这会减慢系统速度,因此请尽量避免这种情况。而且,在我看来,现代系统经常配置过多的交换空间。32GiB RAM通常意味着默认情况下会分配32GiB交换,就好像您真的想将32GiB放入交换空间一样。


哦,我刚刚看到有人在某处上方发表了评论。
sudo

3

可以做的另一件事是通过以下命令释放内存页面缓存:

echo 3 | sudo tee /proc/sys/vm/drop_caches

来自kernel.org文档(添加了重点):

drop_caches

写入此内容将导致内核丢弃干净的缓存以及可回收的平板对象(如牙科和inode)。 一旦删除,他们的记忆就变得自由了

要释放页面缓存:echo 1> / proc / sys / vm / drop_caches要释放可回收的平板对象(包括牙科和索引节点):echo 2> / proc / sys / vm / drop_caches要释放平板对象和页面缓存:echo 3> / proc / sys / vm / drop_caches

这是一种非破坏性操作,不会释放任何脏物。为了增加通过该操作释放的对象数量,用户可以在写入/ proc / sys / vm / drop_caches之前运行“ sync”。这将最大程度地减少系统上脏对象的数量,并创建更多要删除的候选对象。


有趣的...愿意解释该命令逻辑吗?
Akiva

1
@Akiva基本上告诉Linux内核释放RAM。这并不能消除导致破坏性进程的原因,因此Oli的答案就是解决问题的方法。删除高速缓存将防止您的系统内存不足,从而防止冻结,从而使您有时间找出实际问题。这可能比制作交换文件要快一点,尤其是如果您使用硬盘驱动器而不是SSD时
Sergiy Kolodyazhnyy

7
当您填满内存时,缓存是要做的第一件事,因此我认为这不会有太大帮助。实际上,我认为该命令在调试内核行为或优化磁盘访问优化之外没有实际用途。我谨建议不要在需要更高性能的任何系统上运行此命令。
Score_

2
@Score_Under-“缓存是您填满内存时要做的第一件事” –好吧,这取决于您在中的设置/proc/sys/vm/swappiness。将swappiness设置为0,就对了。默认设置为60,您将关闭。但是,将其设置为200时,将首先删除正在运行的进程中使用最少的页面,在这种情况下,此命令可能很有用。但是,将swappiness设置为0(或较低的值,可能是20或30)将是更好的通用方法。
Jules'July

3
@Score_Under此命令在有kswapd错误的旧内核中很有用(有些人甚至使用它创建了cronjobs)。但是你是对的,我怀疑这将有助于解决这个问题。
德米特里·格里戈里耶夫

1

您说“在后台编译”。您在前台做什么?如果您正在使用Eclipse或其他资源密集型IDE进行开发,请检查控制台中的所有内容是否均已正确终止。

开发环境通常允许启动正在开发的多个进程,在您不再对它们感兴趣(在调试器中,或者只是未正确完成)之后,它们也可能会挂起。如果开发人员不注意,一天中可能会累积数十个被遗忘的进程,一起使用多个GB。

检查应终止在IDE中的所有内容是否已终止。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.