Ubuntu Terminal运行服务出现killed

一、问题描述

I ran a job on the Ubuntu server the other day that took 70% of the memory. When I logged one day later to check on it, the job had been killed (it said "killed" in the terminal).

 

二、原因分析

If a process is consuming too much memory then the kernel "Out of Memory" (OOM) killer will automatically kill the offending process. It sounds like this may have happened to your job. The kernel log should show OOM killer actions, so use the "dmesg" command to see what happened, e.g.

dmesg | less
#或者更精准地使用下面命令
dmesg | grep -i kill
#get datetime
dmesg -e | grep -i kill

或者

we can inspect the kernel logs /var/log/kern.log*

The default virtual memory setting for Linux is to over-commit memory. This means the kernel will allow one to allocate more memory than is available, allowing processes to memory map large regions because normally not all the pages in the allocation are used. However, sometimes a process will read/write to all the pages that are over committed and the kernel cannot provide enough physical memory + swap, so the OOM killer attempts to find the best candidate overcommitted process and kill it.

grep /var/log/kern.log* -ie kill
 
简单说明:total-vm就是进程使用的虚拟内存大小,其中部分内容映射到RAM本身,也就是主存,被分配和使用也就成了RSS。
部分RSS在实际内存块里面分配,成了anon-rss,叫做匿名内存。还有映射到设备和文件的RSS内存卡,叫做file-rss。
比如说:
你用vim指令打开一个巨大的文件,那么file-rss将会很高。
如果你用malloc()动态分配很大部分的内存,并且真的使用了它,那么anon-rss也会很高。
但是如果你使用malloc()分配了大量的内存,但是不去用它,total-vm将会变得更高,但是因为内存过量使用,不会使用真正的内存,那么rss值会很低。

Linux 分配内存策略

Linux内核根据应用程序的要求来分配内存,由于进程实际上并不会将分配的内存全部使用,所以,为了提高性能,内核采用了一种过度分配内存(over-commit-memory)的策略,来间接利用进程的空闲内存,提高内存的使用效率。一般来说,这没问题。但如果大多数进程都耗光自己的内存,就有麻烦了。因此此时,所有应用程序的内存之和大于物理内存。所以,必须杀掉一部分进程,一般来说,是选内存占用最大的进程杀掉,但是linux采用的策略并非是杀掉最占用内存的进程(Android是这样)。linux会给每个进程评分:oom_score,根据这个评分去kill,决定这个分数的因素除了内存占用大小之外,还有内存增加的速率,比如说kylin,当执行Task构建Cube的时候,内存的占用会突然爆发式增长,发现这时候的分数很高,然后就把它kill了。

 

三、解决方案

1. 增加系统内存

2. 优化进程,使其占用内存降低。

3. 可以使用oom_score_adj参数,这个参数会被计算影响到oom_score,改了之后就可以避免进程被杀死(不推荐)。

 

oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,分数越低越不会被杀掉。

这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(adj -= 30; 分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来使得进程不容易被 OOM killer 选中杀掉。比如,如果不想 test进程被轻易杀掉的话可以找到 matlab运行的进程号后,调整 oom_score_adj 为 -15(注意 points 越小越不容易被杀):

3.1 TOP看进程PID

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

423 q 20 0 43.012g 3.688g 708928 S 907.3 11.8 700:23.91 xxxx

 

3.2 查看进程的oom_score_adj参数

cat /proc/423/oom_score_adj

0

 

3.3 调整进程的oom_score_adj参数

sudo echo -15 > /proc/423/oom_score_adj

  

也可以完全关闭 OOM killer,但是最好不要这么做

临时生效:

sysctl vm.overcommit_memory=0

sysctl vm.overcommit_memory=1

sysctl vm.overcommit_memory=2

0:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。

1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。

2:表示内核允许分配超过所有物理内存和交换空间总和的内存。

永久生效:

vim /etc/sysctl.conf

vm.overcommit_memory=1

sysctl -p

  

 

 其他优化方案:

  • 代码内存分析(下一篇描述)
  • 使用Supervisor监控服务(提供了基于 Web 的界面来管理所有进程,后续用来做重启) 

 

参考:

How to find out why process was killed on server

Why was Linux process killed?

如何在 Ubuntu 上安装和配置 Supervisor

http://www.wowotech.net/memory_management/oom.html
https://stackoverflow.com/questions/18845857/what-does-anon-rss-and-total-vm-mean

 

posted @ 2022-10-26 17:44  小金乌会发光-Z&M  阅读(542)  评论(0编辑  收藏  举报