linux下进程突然挂掉排查方法

本文详细分析了一台Ubuntu Server 12.04服务器中出现的内存泄漏问题,导致内核频繁调用oom-killer杀死进程的现象。通过检查日志文件和系统状态,最终确定了问题原因在于低内存资源的耗尽,并提供了两种解决方案:升级至64位系统或使用hugemem内核。同时,提供了设置内存参数和关闭oom-killer的方法,帮助用户解决这一常见问题。

环境:

Ubuntu Server 12.04  i686

问题描述:

  1. 24G内存,空闲的有20G左右。但是内核老是报这个,动不动就杀程序 
  2.  
  3. Jul  6 13:12:44 00098 kernel: [3112325.883069] Out of memory: Kill process 2249 (nginx) score 1 or sacrifice child 
  4. Jul  6 13:12:44 00098 kernel: [3112325.922795] Killed process 2831 (nginx) total-vm:21772kB, anon-rss:11048kB, file-rss:916kB 
  5.  
  6. Jul  6 12:43:18 00098 kernel: [3110562.214498] snmpd invoked oom-killer: gfp_mask=0x840d0order=0oom_adj=0oom_score_adj=0 
  7. Jul  6 12:43:18 00098 kernel: [3110562.214502] snmpd cpuset=/ mems_allowed=0 
  8.  
  9. Jul  6 12:49:57 00098 kernel: [3110960.995962] Out of memory: Kill process 1858 (mysqld) score 1 or sacrifice child 
  10. Jul  6 12:49:57 00098 kernel: [3110961.032675] Killed process 1858 (mysqld) total-vm:140652kB, anon-rss:15492kB, file-rss:6100kB 
  11. Jul  6 12:49:57 00098 kernel: [3110961.103870] init: mysql main process (1858) killed by KILL signal 
  12. Jul  6 12:49:57 00098 kernel: [3110961.103899] init: mysql main process ended, respawning 

 

 真的是很郁闷啊,搭建了一个Cacti,系统上刚好有Nginx,所以就用了Nginx,要提供php的支持,还必须安装php5-fpm,安装完成后,登陆上Cacti,过一会儿一刷新,就挂掉了,刚开始还以为是Nginx挂掉了,就没在意,过一会儿,监控报警说Nginx挂掉了,看了下Nginx的日志,没发现异常,今天又发现MySQL挂了,这下蛋疼了,怎么程序动不动就挂呢!仔细分析了一下日志,发现内核报了以上内容,OOM-KILLER这个东西,动不动就杀程序,但是内存并没有满,空的很。

然后网上找了下资料,32位的系统,如果Low-memory耗尽,就会导致这个问题的出现。看了一下Low-memory,确实很少!

通常,在大内存(6Gb+)服务器上,out of memory killer (oom-killer)也会杀死进程。在很多case中,人们都困惑地报告说还有剩余内存的情况下,为何oom-killer还会杀死进程?现象是在 /var/log/messages 日志中,有如下信息:

 

  Out of Memory: Killed process [PID] [process name].

在我自己的case中,我在VMware中升级了各个RHEL3到RHEL4,有1个16Gb内存的服务器,还是会被oom-killer杀死进程。不用说,这非常令人沮丧。

 

事实证明,这个问题的原因是low memory耗尽。引用Tom的话“内核使用low memory来跟踪所有的内存分配,这样的话一个16GB内存的系统比一个4GB内存的系统,需要消耗更多的low memory,可能有4倍之多。这种额外的压力从你刚启动系统那一刻就开始存在了,因为内核结构必须为潜在的跟踪四倍多的内存分配而调整大小

说白了 OOM Killer 就是一层保护机制,用于避免 Linux 在内存不足的时候不至于出太严重的问题,把无关紧要的进程杀掉,有些壮士断腕的意思。

先要学习点老知识,在 32 位CPU 架构下寻址是有限制的。Linux 内核定义了三个区域:


  1. # DMA: 0x00000000 -  0x00999999 (0 - 16 MB) 
  2.  
  3. # LowMem: 0x01000000 - 0x037999999 (16 - 896 MB) - size: 880MB 
  4.  
  5. # HighMem: 0x038000000 - <硬件特定> 

LowMem 区 (也叫 NORMAL ZONE ) 一共 880 MB,而且不能改变(除非用 hugemem 内核)。对于高负载的系统,就可能因为 LowMem 利用不好而引发 OOM Killer 。一个可能原因是 LowFree 太少了,另外一个原因是 LowMem 里都是碎片,请求不到连续的内存区域

 

有两种方法查看 low memory 和 high memory 的状态:

 

  1. # egrep 'High|Low' /proc/meminfo 
  2. HighTotal:     5111780 kB 
  3. HighFree:         1172 kB 
  4. LowTotal:       795688 kB 
  5. LowFree:         16788 kB 
  6.  
  7. # free -lm 
  8.              total       used       free     shared    buffers     cached 
  9. Mem:          5769       5751         17          0          8       5267 
  10. Low:           777        760         16          0          0          0 
  11. High:         4991       4990          1          0          0          0 
  12. -/+ buffers/cache:        475       5293 
  13. Swap:         4773          0       4773 
当low memory耗尽,不管high memory剩余多少,oom-killer都开始杀死进程,以保持系统的正常运转。

有两种方法可以解决这个问题

1、如果可能,请升级到64位系统。

这是最好的解决办法,因为所有的内存都将成为low memory。如果你在这种情况下耗尽了low memory,那就真的是out of memory了。

2、如果受限于必须使用32位系统,最好的解决办法是使用hugemem内核。

这种内核以不同的方式分割low/high memory,而且在大多数情况下会提供足够多的low memory到high memory的映射。在大多数案例中,这是一个很简单的修复方法:安装hugemem kernel RPM包,然后重启即可。

如果运行hugemem内核也不可能,你可以尝试将/proc/sys/vm/lower_zone_protection 的值设置为250甚至更多。这将让内核愿意保护low memory,从而在分配内存时多考虑从high memory分配。据我所知,此选项从2.6.x内核才开始可用。必要的是,您可能需要通过一些实验来找到您系统环境中最适合的值。可以使用下面方法快速的设置和检查改值:

 

  1. # cat /proc/sys/vm/lower_zone_protection 
  2. # echo "250" > /proc/sys/vm/lower_zone_protection 

在 /etc/sysctl.conf 中加入设置,以便启动就生效:

  vm.lower_zone_protection = 250

作为最后的努力,你可以关闭oom-killer。这个选项可以导致系统挂起,所以请小心使用(风险自负)!

查看当前oom-killer的状态:

 

  1. # cat /proc/sys/vm/oom-kill 

关闭/打开oom-killer:

 

  1. # echo "0" > /proc/sys/vm/oom-kill 
  2. # echo "1" > /proc/sys/vm/oom-kill 

 

当进程该被oom-killer杀死却没有被杀死时,相关信息会记录到 /var/log/messages:

"Would have oom-killed but /proc/sys/vm/oom-kill is disabled"


参考 :http://www.360doc.com/content/13/0706/23/13063437_298141724.shtml

<think>好的,用户问的是踩内存导致的进程挂掉问题如何排查。首先,我需要理解什么是踩内存。踩内存通常指的是内存越界访问,比如数组越界或者使用了野指针,导致访问了不属于自己的内存区域,进而引发程序崩溃。 接下来,我需要回忆常见的排查方法。可能想到的有使用调试器(比如gdb)、内存检查工具(如valgrind)、代码审查、日志分析等。还要考虑核心转储(core dump)的生成和分析,以及如何复现问题。 用户可能是在开发过程中遇到了这类问题,需要实际的解决步骤。他们可能对底层调试不太熟悉,所以需要详细但清晰的步骤。此外,用户可能关心如何预防这类问题,或者如何高效地定位问题根源,而不仅仅是表面现象。 需要分步骤说明排查方法,比如启用core dump,用gdb分析,使用valgrind检查内存问题,检查代码中的常见错误,比如指针操作和数组访问。另外,可能还要提到静态代码分析工具,以及如何通过日志缩小问题范围。 还要注意用户可能的环境,比如Linux系统,所以工具和方法要基于Linux。需要确保提供的示例命令正确,比如ulimit设置,gdb的使用方式,valgrind的参数等。 最后,相关问题需要涵盖核心转储配置、工具使用、常见错误类型、预防措施以及日志的作用。确保问题覆盖用户可能的后续疑问,帮助他们全面了解排查流程。</think>排查踩内存引起的进程崩溃问题需通过以下步骤定位并修复: --- ### **1. 生成核心转储文件(Core Dump)** - **启用Core Dump**: ```bash ulimit -c unlimited # 解除Core文件大小限制 echo "/tmp/core.%e.%p" > /proc/sys/kernel/core_pattern # 设置生成路径和文件名格式 ``` - **触发崩溃后**:检查 `/tmp` 或指定路径下是否生成 `core.*` 文件。 --- ### **2. 使用GDB分析Core Dump** - **加载Core文件**: ```bash gdb <可执行文件路径> <core文件路径> ``` - **关键命令**: ```gdb bt full # 查看崩溃时的堆栈信息 info registers # 检查寄存器状态(如PC指针指向非法地址) disassemble # 反汇编当前执行的代码段 ``` --- ### **3. 使用Valgrind检测内存问题** - **运行程序时检测**: ```bash valgrind --tool=memcheck ./your_program ``` - **常见输出**: - `Invalid read/write`:提示非法内存访问 - `Address is`:显示访问的非法地址及上下文 --- ### **4. 检查代码中的高风险操作** - **数组越界**: ```c int arr[10]; arr[20] = 0; // 越界访问 ``` - **野指针/悬空指针**: ```c int *p = malloc(4); free(p); *p = 10; // 使用已释放的内存 ``` - **内存泄漏(间接导致)**: ```c while (1) { malloc(100); // 未释放内存,可能耗尽地址空间 } ``` --- ### **5. 静态代码分析** - **工具**:`cppcheck`、`clang-tidy`(C/C++)、`Coverity`(商业工具) - **检查内容**:未初始化指针、资源释放后二次使用、类型转换错误等。 --- ### **6. 日志与复现** - **添加日志**:在崩溃点附近添加 `printf` 或日志输出,缩小问题范围。 - **复现条件**:尝试通过压力测试、特定输入触发问题(如大文件、多线程并发)。 --- ### **7. 防御性编程** - **初始化指针**:`malloc` 后立即检查返回值,释放后置 `NULL`。 - **使用安全函数**:如 `strncpy` 替代 `strcpy`,避免缓冲区溢出。 - **内存屏障**:在多线程场景中使用原子操作或锁保护共享内存。 --- ### **示例:GDB定位崩溃堆栈** ```gdb (gdb) bt #0 0x00000000004005f6 in faulty_function () at test.c:10 #1 0x0000000000400612 in main () at test.c:15 ``` 提示崩溃发生在 `test.c` 第10行的 `faulty_function` 中。 --- ### **相关问题** 1. 如何配置Linux系统生成Core Dump文件? 2. Valgrind的Memcheck工具如何检测内存越界访问? 3. 常见的踩内存错误类型有哪些?如何通过代码规范避免? 4. 如何通过静态代码分析工具提前发现潜在内存问题? 5. 在多线程程序中,踩内存问题如何结合日志定位?
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值