使用 /var/log/messages 调试内存不足

ibe*_*ski 50 linux logs memory out-of-memory

我的消息日志中抛出了以下报告:

kernel: Out of memory: Kill process 9163 (mysqld) score 511 or sacrifice child
kernel: Killed process 9163, UID 27, (mysqld) total-vm:2457368kB, anon-rss:816780kB, file-rss:4kB
Run Code Online (Sandbox Code Playgroud)

如果这个问题是针对 的并不重要httpdmysqld或者postfix我很好奇如何继续调试问题。

我怎样才能获得更多关于为什么 PID 9163 被杀死的信息,我不确定 linux 是否在某处保留终止的 PID 的历史记录。

如果您的消息日志文件中出现这种情况,您将如何逐步解决此问题?

# free -m

             total       used       free     shared    buffers     cached
Mem:          1655        934        721          0         10         52
-/+ buffers/cache:        871        784
Swap:          109          6        103`
Run Code Online (Sandbox Code Playgroud)

gol*_*cks 66

内核会在发生这种情况之前记录一堆东西,但其中大部分可能不会在 中/var/log/messages,这取决于您(r)syslogd的配置方式。尝试:

grep oom /var/log/*
grep total_vm /var/log/*
Run Code Online (Sandbox Code Playgroud)

前者应该出现很多次,而后者只出现在一两个地方。那就是您要查看的文件。

在其中一个还包含total_vm. 在该行之前的 30 秒到一分钟(可能更多,也可能更少),您会发现以下内容:

kernel: foobar invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0
Run Code Online (Sandbox Code Playgroud)

您还应该在该行和“内存不足”行之间的某处找到一个表,标题如下:

[ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
Run Code Online (Sandbox Code Playgroud)

这可能不会告诉您比您已经知道的更多,但这些字段是:

  • pid进程 ID。
  • uid用户 ID。
  • tgid线程组 ID。
  • total_vm虚拟内存使用(4 kB 页)
  • rss驻留内存使用(以 4 kB 页计)
  • nr_ptes页表条目
  • swapents掉期项
  • oom_score_adj通常为0;较低的数字表示在调用 OOM 杀手时该进程不太可能死亡。

你大多可以忽略nr_ptesswapents尽管我相信这些是决定谁被杀的因素。这不一定是使用最多内存的进程,但很可能是。有关选择过程的更多信息,请参见此处。基本上,以最高 oom 分数结束的进程会被终止——这是“内存不足”行上报告的“分数”;不幸的是,没有报告其他分数,但该表提供了一些因素方面的线索。

同样,这可能只会说明显而易见的事情:系统内存不足mysqld并被选择死亡,因为杀死它会释放最多的资源。这并不一定意味着mysqld做错了什么。您可以查看该表,看看当时是否还有其他异常情况,但可能没有任何明确的罪魁祸首:系统可能会因为您错误判断或错误配置正在运行的进程而耗尽内存。

  • `dmesg` 是可以保证的地方。如果 syslog 守护进程从 `/dev/kmsg` 读取(尽管它通常会这样做),它只会在 `/var/log` 中。 (5认同)
  • @Patrick 这取决于*何时*你去看。如果它记录在一个正常的文件日志中(应该是,或者你用你的记录器做了一些愚蠢的事情),它会在那里很长时间,而此时,如果 OP 想要诊断发生的问题昨天或前一天等,即使系统保持运行,记录也可能不再在 `dmesg` 中。 (3认同)

mjt*_*ner 6

关键在于消息本身——内存不足。当 Linux 内核缺乏虚拟内存(物理 RAM 加上交换)时,它将开始杀死进程,而这正是这里发生的情况。看起来mysqld使用了超过 2GB 的虚拟内存。

系统有多少 RAM 和交换空间?我会考虑添加额外的 RAM,或者,如果不可能,添加额外的交换。作为至少防止进程被终止的快速修复,您可以添加一个交换文件。

更新:查看您拥有的 RAM 量,您可以立即看到问题所在。您有大约 1.6GB 的 RAM 和 100MB 的交换空间,但 MySQL 使用的 RAM 比这多得多。这解释了为什么您会看到进程被终止。