linux中引起OOM Killer的原因及排查思路

2024-08-23 21:12

本文主要是介绍linux中引起OOM Killer的原因及排查思路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OOM Killer(Out-Of-Memory Killer)的触发通常是由于Linux系统内存不足时,内核采取的一种极端保护措施。具体来说,OOM Killer触发的原因主要有以下几个方面:

一、触发OOM Killer原因

  • 系统内存耗尽

当系统物理内存(RAM)和交换空间(Swap)都被大量占用,无法满足新的内存分配请求时,OOM Killer会被触发。这通常发生在高负载的服务器上,当多个内存密集型应用同时运行时,系统内存很快就会被耗尽。

  • 内存分配失败

当某个进程尝试分配内存,但系统无法满足其请求时,内核会尝试通过回收内存(如页面回收、文件缓存回收等)来释放空间。如果回收的内存仍然不足,OOM Killer将被激活,以选择并终止某些进程来释放内存。

  • 内存泄漏

应用程序中的内存泄漏问题也可能导致OOM Killer的触发。内存泄漏是指程序在运行过程中,无法释放已经不再使用的内存空间,导致内存不断被占用,最终耗尽系统资源。

  • 特定进程的内存需求

某些进程可能因为内存需求过大,或者请求大块连续内存而触发OOM Killer。在32位系统中,由于地址空间的限制,大内存请求更容易导致问题。

  • 系统配置和策略

Linux内核提供了多种配置选项和策略,用于控制OOM Killer的行为。例如,可以通过调整/proc/sys/vm/oom_kill_allocating_task的值来决定是否杀死尝试分配内存的进程。此外,还可以通过设置进程的OOM得分(oom_score_adj)来调整其被OOM Killer选中的优先级。

  • 内核和硬件限制

在某些情况下,内核或硬件的限制也可能导致OOM Killer的触发。例如,在NUMA(Non-Uniform Memory Access)架构的系统中,节点间的内存分配限制可能导致OOM Killer的激活。

当OOM Killer被触发时,内核会计算每个进程的OOM得分,并选择得分最高的进程进行终止。OOM得分通常基于进程的内存使用量、优先级、类型等因素来计算。被终止的进程及其内存释放信息会被记录在系统日志中,以便管理员进行后续分析和处理。

二、排查思路

  1. 实时监控:通过系统监控工具(如tophtopfreevmstat等)查看当前系统内存使用情况,包括物理内存和交换空间。
  2. 检查系统日志:查看/var/log/messagesdmesg输出,寻找OOM Killer的相关信息,内核会在触发OOM Killer时记录相关信息,包括被杀掉的进程及其理由。
  3. 分析OOM Killer报告:当OOM Killer启动时,它会生成一个详细的报告,指出为何选择特定进程进行终止。可以通过这些信息来识别最可能的内存消耗大户。
  4. 定位消耗内存的进程:利用pspmapsmem等工具定位消耗内存最多的进程,并进一步分析其行为和资源需求。
  5. 检查程序日志和代码:如果确定是某个应用程序导致的OOM,应查看该程序的日志文件,了解其运行时的内存使用情况。同时,对代码进行审计,查找是否存在内存泄漏或其他不当内存管理。
  6. 启用内核OOME日志:在系统启动参数中加入vm.panic_on_oom=0vm.overcommit_memory=2(或适当调整内存过载策略),以便在发生OOM时让内核生成更详细的日志。
  7. 长期监控与趋势分析:使用像Prometheus + Grafana这样的监控系统长期收集内存使用数据并进行趋势分析,有助于提前发现潜在的内存使用增长问题。
  8. 优化资源配置:根据实际情况调整系统或容器的内存限制,优化程序以降低内存消耗,或者考虑增加物理内存和交换空间。
  9. 针对特定问题解决方案:例如,在图像处理或大数据场景中,采用合适的内存管理和缓存策略,避免一次性加载所有数据到内存中。对于Java应用,可通过调整JVM参数等方式优化内存管理。

三、优化建议

为了避免OOM Killer的触发,可以采取以下措施:

  • 优化内存使用:检查并优化应用程序的内存使用,避免内存泄漏和不必要的内存占用。
  • 增加内存资源:在系统允许的情况下,增加物理内存或交换空间的大小。
  • 调整OOM Killer策略:通过修改系统配置,调整OOM Killer的行为和优先级策略。
  • 监控和预警:使用系统监控工具实时监控系统内存使用情况,及时发现并处理内存不足的问题。

四、实例分析

1、ls触发OMM

Aug 17 03:12:59 Hygonrbej01 kernel: [159440.49643] ls invoked oom-killer: gfp_mask=0x6040c0(GFP_KERNEL|__GFP_COMP), nodemask=(null), order=3, oom_score_adj=0
Aug 17 03:12:59 Hygonrbej01 kernel: [159440.49646] ls cpuset=/ mems_allowed=0
Aug 17 03:12:59 Hygonrbej01 kernel: [159440.49652] CPU: 0 PID: 389525 Comm: ls Kdump: loaded Tainted: GOE  4.19.90-23.26.v2101.ky10.x86_64 #1

这段日志显示了Linux系统中的一个内存不足(OOM, Out of Memory)事件,具体是由ls命令触发的。ls命令是一个常用的列出目录内容的命令,但在某些情况下,如果它试图读取或处理大量文件,并且系统内存已经接近耗尽,就可能会触发OOM Killer。不过,在这个特定的例子中,ls命令本身作为OOM Killer的受害者似乎有些不寻常,因为ls通常不会消耗大量内存。这可能是由于其他因素导致的,比如系统内存已经极度紧张,或者ls命令在处理某些特殊文件或目录时遇到了问题。

以下是日志中关键信息的解释:

  • OOM Killer被调用:日志中的ls invoked oom-killer表明ls进程是触发OOM Killer的“罪魁祸首”。但请注意,这并不一定意味着ls是内存泄漏或过度使用内存的源头;它可能只是在系统内存已经严重不足时尝试分配内存的众多进程之一。

  • 内存分配请求gfp_mask=0x6040c0(GFP_KERNEL|__GFP_COMP)表示这是一个内核内存分配请求,使用了GFP_KERNEL__GFP_COMP标志。GFP_KERNEL是内核分配内存时最常用的标志,表示可以等待内存释放;__GFP_COMP可能是一个与内存压缩相关的标志,但在较新的Linux版本中可能不再使用或已更改含义。

  • 节点和CPU信息nodemask=(null)表明没有特定的NUMA节点偏好;CPU: 0表明OOM Killer的日志是在CPU 0上记录的。

  • 进程信息PID: 389525 Comm: ls显示了被OOM Killer选中的进程ID(PID)和命令名(Comm)。

  • 系统信息:包括硬件名称、BIOS版本等信息,这些信息对于分析系统环境和可能的问题源很有帮助。

  • 调用栈Call Trace部分显示了导致OOM Killer被触发的函数调用栈。这有助于开发者或系统管理员了解在内存分配失败时,系统是如何处理并最终决定杀死某个进程的。

  • 内存信息(Mem-Info):这部分提供了关于系统内存使用情况的详细统计,包括活跃和非活跃的内存、slab内存、映射的内存、共享内存等。这些信息对于诊断内存问题非常有用。

2、Java进程被kill9

Aug 17 03:12:59 Hygonrbej01 kernel: [159440.49894] Out of memory: Kill process 3067998 (java) score 244 or sacrifice child
Aug 17 03:12:59 Hygonrbej01 kernel: [159440.50254] Killed process 367998 (java) total-vm:12717748kB, anon-rss:3581268kB, file-rss:3936kB, shmem-rss:20kB
Aug 17 03:12:59 Hygonrbej01 kernel: [159440.19186] oom_reaper: reaped process 3067998 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:20kB
Aug 17 03:12:59 Hygonrbej01 systemd[1]: bes.service: Main process exited, code=killed, status=9/KILL
Aug 17 03:12:59 Hygonrbej01 systemd[1]: bes.service: Failed with result 'signal'.

这段日志记录了几个关键事件,主要涉及系统内存管理、服务失败。下面是对这些事件的详细解释:

  1. 内存不足(OOM Killer 触发)
    • Out of memory: Kill process 3067998 (java) score 244 or sacrifice child:这表示系统遇到了内存不足(Out of Memory, OOM)的情况,OOM Killer 被激活以杀死一些进程以释放内存。它选择了进程ID为3067998的Java进程作为牺牲品,因为这个进程的OOM分数(score)最高,为244。OOM分数是基于进程占用的内存量、优先级等因素计算得出的。
  2. Java进程被杀死
    • Killed process 3067998 (java) total-vm:12717748kB, anon-rss:3581268kB, file-rss:3936kB, shmem-rss:20kB:这进一步确认了Java进程(PID 3067998)已被杀死。该进程占用的总虚拟内存(total-vm)为12,717,748kB,匿名可回收内存(anon-rss)为3,581,268kB,文件映射内存(file-rss)为3,936kB,共享内存(shmem-rss)为20kB。
  3. OOM Reaper 清理
    • oom_reaper: reaped process 3067998 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:20kB:OOM Reaper 是一个内核线程,负责清理OOM Killer杀死的进程留下的资源。这里显示Java进程的匿名可回收内存和文件映射内存已被清零,但共享内存(可能是因为它不是由该进程独占的)保持不变。
  4. 服务失败
    • systemd[1]: bes.service: Main process exited, code=killed, status=9/KILLsystemd[1]: bes.service: Failed with result 'signal':这表明一个名为bes.service的服务的主进程被信号(这里是KILL信号)杀死,导致服务失败。这很可能与前面提到的Java进程被杀有关,如果该Java进程是该服务的一部分。

这篇关于linux中引起OOM Killer的原因及排查思路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100509

相关文章

防止Linux rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Linux查询服务器 IP 地址的命令详解

《Linux查询服务器IP地址的命令详解》在服务器管理和网络运维中,快速准确地获取服务器的IP地址是一项基本但至关重要的技能,下面我们来看看Linux中查询服务器IP的相关命令使用吧... 目录一、hostname 命令:简单高效的 IP 查询工具命令详解实际应用技巧注意事项二、ip 命令:新一代网络配置全

linux安装、更新、卸载anaconda实践

《linux安装、更新、卸载anaconda实践》Anaconda是基于conda的科学计算环境,集成1400+包及依赖,安装需下载脚本、接受协议、设置路径、配置环境变量,更新与卸载通过conda命令... 目录随意找一个目录下载安装脚本检查许可证协议,ENTER就可以安装完毕之后激活anaconda安装更