由于内存不足,服务器有崩溃的风险。The server runs the risk of crashing because it ran out of memory。为了防止服务器到达这个临近状态,内核中有一个OOM Killer杀手进程。To prevent the server from reaching that critical state, the kernel also contains a process known as the OOM Killer。内核利用这个杀手进程开始屠杀那些非必要进程,以便服务器正常运行。The kernel uses this process to start killing non-essential processes so the server can remain operational.
当你认为这一切都不是问题时,因为OOM Killer只杀掉那些非必要的,不是用户需要的进程。举例,两个应用(Apache和MySQL)通常先被杀掉,因为占用大量的内存。但这将导致一个web网站立马瘫痪了。
当尝试找到为什么一个应用程序或进程被OOM killer杀掉时,有很多地方可以找到一个进程如何被杀掉以及被杀掉的原因。
$ grep -i kill /var/log/messages*
host kernel: Out of Memory: Killed process 5123 (exampleprocess)
The capital K in Killed tells you that the process was killed with a -9 signal, and this typically is a good indicator that the OOM Killer is to blame.
$ free -lh
The -l switch shows high and low memory statistics, and the -h switch puts the output into gigabytes for easier human readability. You can change this to the -m switch if you prefer the output in megabytes.
同时该命令会给出Swap内存使用信息。注意:free命令给出某个时刻得数据,需要多执行几次才能知道内存动态的占用情况。
$ vmstat -SM 10 20
20次,每次间隔10秒给出内存使用情况。
top 默认输出CPU的使用情况,不过你可以在top后再按下shift + M,你将得到内存的使用情况。
配置文件/etc/sysctl.conf:
sysctl vm.panic_on_oom=1
sysctl kernel.panic=X
echo “vm.panic_on_oom=1” >>/etc/sysctl.conf
echo “kernel.panic=X” >>/etc/sysctl.conf
大多数情况下,内存不足时每次都重启是不合适的。
既可以保护一些重要进程不被OMM killer杀掉,又可以让不重要的进程更容易杀掉:
echo -15 >/proc/(PID)/oom_adj (不被杀)
echo 10 >/proc/(PID)/oom_adj (更易杀)
pstree -p | grep "process" | head -1
在某些情况下,豁免进程可能导致意外的行为变化,取决于系统和资源配置。假如内核无法杀死一个占用大量内存的进程,将杀死其他进程,包括那些重要的 *** 作系统进程。
由于OOM killer可调节的有效范围在-16到+15之间,设置为-17将豁免一个进程,因为在OOM killer调节范围之外。通常的规则是这个参数越大越容易被杀死豁免一个进程的命令是
echo -17 >/proc/(PID)/oom_adj
警告:不建议用于生产环境。
假如重启,修改进程优先级,豁免一个进程不足够好,有个风险的选项:将oom killer 功能关闭。
这一选项参数将有如下影响:
4.1) 严重的内核恐慌kernel panic
4.2) 系统挂住system hang-up
4.3) 一个完整的系统崩溃system crash
为什么关闭有风险呢呢?该功能避免自己因资源而跑飞了。如果你关闭此功能,将不能避免内存耗尽。考虑此项时请极度慎重。
sysctl vm.overcommit_memory=2
echo “vm.overcommit_memory=2” >>/etc/sysctl.conf
kill -9 发送SIGKILL信号给进程,将其终止,但对于以下两种情况不适用 1.该进程是僵尸进程(STAT z),此时进程已经释放所有的资源,但是没有被父进程释放。僵尸进程要等到父进程结束,或者重启系统才可以被释放。 2.进程处于“核心态”,并且在等待不可获得的资源,处于“核心态 ”的资源默认忽略所有信号。只能重启系统。 kill 只能杀死处于用户状态的进程。 下面是一个自测试例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> int main(int argc ,char *argv[]) { pid_t pid pid = fork() if(pid<0){ perror("fork") return -1 }else if(pid==0){ printf("I am a child\n") exit(0) }else{ while(1){ sleep(100) } } return 0 } 由于父进程没有退出,所以执行ps -aux | grep "z",可以查看进程的状态,发现如下(绿色标出部分) root 1937 0.0 0.1 389000 4336 ? Sl 09:12 0:00 /usr/bin/gnome-keyring-daemon --daemonize --login root 4447 0.0 0.0 112680 964 pts/2 R+ 10:16 0:00 grep --color=auto z [root@localhost linux_test]# ps -aux | grep "[zZ]" USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 128164 6828 ? Ss 09:07 0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 root 1937 0.0 0.1 389000 4336 ? Sl 09:12 0:00 /usr/bin/gnome-keyring-daemon --daemonize --login root 4385 0.0 0.0 0 0 pts/0 Z+ 10:16 0:00 [a.out] <defunct> root 4455 0.0 0.0 112680 976 pts/2 S+ 10:17 0:00 grep --color=auto [zZ] 从以上信息 可以得到该进程的进程号是4385 此时的解决方法有两种 《1》 cat /proc/4385/status 找到该子进程对应的父进程,将其父进程杀死 State: Z (zombie) Tgid: 4385 Ngid: 0 Pid: 4385 PPid: 4384 执行kill -9 4384 如果父进程也杀不死,那就只能执行重启了 《2》重启欢迎分享,转载请注明来源:内存溢出
评论列表(0条)