我的应用程序在 Linux 上作为后台进程运行。它当前在终端窗口的命令行中启动。
最近一个用户执行了一段时间的应用程序,它神秘地死了。文本:
被杀
在终端上。这发生了两次。我问是否有人在不同的终端使用 kill 命令杀死进程?不。
Linux 在什么情况下会决定终止我的进程?我相信 shell 显示“killed”是因为进程在收到 kill(9) 信号后死亡。如果 Linux 发送了终止信号,系统日志中是否应该有一条消息解释它为什么被终止?
如果用户或系统管理员没有杀死内核可能拥有的程序。内核只会在资源极度匮乏(想想 mem+swap 耗尽)等特殊情况下杀死进程。
尝试:
dmesg -T| grep -E -i -B100 'killed process'
where-B100
表示杀死发生之前的行数。
在 Mac OS 上省略-T 。
这看起来像是一篇关于这个主题的好文章:驯服 OOM 杀手。
要点是 Linux过度使用记忆。当一个进程请求更多空间时,Linux 会给它这个空间,即使它被另一个进程占用,假设没有人真正使用他们请求的所有内存。该进程将在实际使用它分配的内存时独占使用它,而不是在它请求时。这使得分配速度更快,并且可能允许您“作弊”并分配比实际更多的内存。然而,一旦进程开始使用这个内存,Linux 可能会意识到它在分配它没有的内存方面过于慷慨,并且必须终止一个进程以释放一些内存。要杀死的进程是基于考虑运行时(长时间运行的进程更安全)、内存使用量(贪婪进程不太安全)和其他一些因素的分数,包括一个您可以调整的值,以使进程不太可能被杀死。这一切都在文章中进行了更详细的描述。
编辑:这是另一篇文章,很好地解释了如何选择进程(用一些内核代码示例进行注释)。这样做的好处是它包含了对各种规则背后的推理的一些评论。badness()
假设您有 512 RAM + 1GB 交换内存。所以理论上,你的 CPU 可以访问总共 1.5GB 的虚拟内存。
现在,一段时间以来,在 1.5GB 的总内存中一切都运行良好。但是突然(或逐渐)您的系统开始消耗越来越多的内存,并且达到了所用总内存的 95% 左右。
现在假设任何进程都向内核请求了大块内存。内核检查可用内存并发现它无法为您的进程分配更多内存。所以它会尝试释放一些内存调用/调用 OOMKiller ( http://linux-mm.org/OOM )。
OOMKiller 有自己的算法来为每个进程评分。通常哪个进程使用更多内存成为被杀死的受害者。
通常在 /var/log 目录中。/var/log/kern.log 或 /var/log/dmesg
希望这会帮助你。
这是 Linux内存不足管理器 (OOM)。选择您的进程是因为“糟糕”——最近性、驻留大小(正在使用的内存,而不仅仅是分配的内存)和其他因素的组合。
sudo journalctl -xb
您会看到如下消息:
Jul 20 11:05:00 someapp kernel: Mem-Info:
Jul 20 11:05:00 someapp kernel: Node 0 DMA per-cpu:
Jul 20 11:05:00 someapp kernel: CPU 0: hi: 0, btch: 1 usd: 0
Jul 20 11:05:00 someapp kernel: Node 0 DMA32 per-cpu:
Jul 20 11:05:00 someapp kernel: CPU 0: hi: 186, btch: 31 usd: 30
Jul 20 11:05:00 someapp kernel: active_anon:206043 inactive_anon:6347 isolated_anon:0
active_file:722 inactive_file:4126 isolated_file:0
unevictable:0 dirty:5 writeback:0 unstable:0
free:12202 slab_reclaimable:3849 slab_unreclaimable:14574
mapped:792 shmem:12802 pagetables:1651 bounce:0
free_cma:0
Jul 20 11:05:00 someapp kernel: Node 0 DMA free:4576kB min:708kB low:884kB high:1060kB active_anon:10012kB inactive_anon:488kB active_file:4kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present
Jul 20 11:05:00 someapp kernel: lowmem_reserve[]: 0 968 968 968
Jul 20 11:05:00 someapp kernel: Node 0 DMA32 free:44232kB min:44344kB low:55428kB high:66516kB active_anon:814160kB inactive_anon:24900kB active_file:2884kB inactive_file:16500kB unevictable:0kB isolated(anon):0kB isolated
Jul 20 11:05:00 someapp kernel: lowmem_reserve[]: 0 0 0 0
Jul 20 11:05:00 someapp kernel: Node 0 DMA: 17*4kB (UEM) 22*8kB (UEM) 15*16kB (UEM) 12*32kB (UEM) 8*64kB (E) 9*128kB (UEM) 2*256kB (UE) 3*512kB (UM) 0*1024kB 0*2048kB 0*4096kB = 4580kB
Jul 20 11:05:00 someapp kernel: Node 0 DMA32: 216*4kB (UE) 601*8kB (UE) 448*16kB (UE) 311*32kB (UEM) 135*64kB (UEM) 74*128kB (UEM) 5*256kB (EM) 0*512kB 0*1024kB 1*2048kB (R) 0*4096kB = 44232kB
Jul 20 11:05:00 someapp kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
Jul 20 11:05:00 someapp kernel: 17656 total pagecache pages
Jul 20 11:05:00 someapp kernel: 0 pages in swap cache
Jul 20 11:05:00 someapp kernel: Swap cache stats: add 0, delete 0, find 0/0
Jul 20 11:05:00 someapp kernel: Free swap = 0kB
Jul 20 11:05:00 someapp kernel: Total swap = 0kB
Jul 20 11:05:00 someapp kernel: 262141 pages RAM
Jul 20 11:05:00 someapp kernel: 7645 pages reserved
Jul 20 11:05:00 someapp kernel: 264073 pages shared
Jul 20 11:05:00 someapp kernel: 240240 pages non-shared
Jul 20 11:05:00 someapp kernel: [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
Jul 20 11:05:00 someapp kernel: [ 241] 0 241 13581 1610 26 0 0 systemd-journal
Jul 20 11:05:00 someapp kernel: [ 246] 0 246 10494 133 22 0 -1000 systemd-udevd
Jul 20 11:05:00 someapp kernel: [ 264] 0 264 29174 121 26 0 -1000 auditd
Jul 20 11:05:00 someapp kernel: [ 342] 0 342 94449 466 67 0 0 NetworkManager
Jul 20 11:05:00 someapp kernel: [ 346] 0 346 137495 3125 88 0 0 tuned
Jul 20 11:05:00 someapp kernel: [ 348] 0 348 79595 726 60 0 0 rsyslogd
Jul 20 11:05:00 someapp kernel: [ 353] 70 353 6986 72 19 0 0 avahi-daemon
Jul 20 11:05:00 someapp kernel: [ 362] 70 362 6986 58 18 0 0 avahi-daemon
Jul 20 11:05:00 someapp kernel: [ 378] 0 378 1621 25 8 0 0 iprinit
Jul 20 11:05:00 someapp kernel: [ 380] 0 380 1621 26 9 0 0 iprupdate
Jul 20 11:05:00 someapp kernel: [ 384] 81 384 6676 142 18 0 -900 dbus-daemon
Jul 20 11:05:00 someapp kernel: [ 385] 0 385 8671 83 21 0 0 systemd-logind
Jul 20 11:05:00 someapp kernel: [ 386] 0 386 31573 153 15 0 0 crond
Jul 20 11:05:00 someapp kernel: [ 391] 999 391 128531 2440 48 0 0 polkitd
Jul 20 11:05:00 someapp kernel: [ 400] 0 400 9781 23 8 0 0 iprdump
Jul 20 11:05:00 someapp kernel: [ 419] 0 419 27501 32 10 0 0 agetty
Jul 20 11:05:00 someapp kernel: [ 855] 0 855 22883 258 43 0 0 master
Jul 20 11:05:00 someapp kernel: [ 862] 89 862 22926 254 44 0 0 qmgr
Jul 20 11:05:00 someapp kernel: [23631] 0 23631 20698 211 43 0 -1000 sshd
Jul 20 11:05:00 someapp kernel: [12884] 0 12884 81885 3754 80 0 0 firewalld
Jul 20 11:05:00 someapp kernel: [18130] 0 18130 33359 291 65 0 0 sshd
Jul 20 11:05:00 someapp kernel: [18132] 1000 18132 33791 748 64 0 0 sshd
Jul 20 11:05:00 someapp kernel: [18133] 1000 18133 28867 122 13 0 0 bash
Jul 20 11:05:00 someapp kernel: [18428] 99 18428 208627 42909 151 0 0 node
Jul 20 11:05:00 someapp kernel: [18486] 89 18486 22909 250 46 0 0 pickup
Jul 20 11:05:00 someapp kernel: [18515] 1000 18515 352905 141851 470 0 0 npm
Jul 20 11:05:00 someapp kernel: [18520] 0 18520 33359 291 66 0 0 sshd
Jul 20 11:05:00 someapp kernel: [18522] 1000 18522 33359 294 64 0 0 sshd
Jul 20 11:05:00 someapp kernel: [18523] 1000 18523 28866 115 12 0 0 bash
Jul 20 11:05:00 someapp kernel: Out of memory: Kill process 18515 (npm) score 559 or sacrifice child
Jul 20 11:05:00 someapp kernel: Killed process 18515 (npm) total-vm:1411620kB, anon-rss:567404kB, file-rss:0kB
正如 dwc 和 Adam Jaskiewicz 所说,罪魁祸首很可能是 OOM Killer。然而,接下来的下一个问题是:如何防止这种情况发生?
有几种方法:
多亏了这篇文章,我发现(2)特别容易实现。
像 systemtap(或跟踪器)这样的工具可以监控内核信号传输逻辑并报告。例如,https://sourceware.org/systemtap/examples/process/sigmon.stp
# stap --example sigmon.stp -x 31994 SIGKILL
SPID SNAME RPID RNAME SIGNUM SIGNAME
5609 bash 31994 find 9 SIGKILL
该脚本中的过滤if
块可以进行调整以适应口味,或消除以跟踪系统范围的信号流量。通过收集回溯可以进一步隔离原因(分别为内核和用户空间添加一个print_backtrace()
和/或探针)。print_ubacktrace()
在 lsf 环境(交互式或其他方式)中,如果应用程序的内存利用率超出队列管理员的某个预设阈值或提交到队列的资源请求,则进程将被终止,因此其他用户不会成为潜在的受害者逃跑。它并不总是在发送电子邮件时发送电子邮件,具体取决于其设置方式。
在这种情况下,一种解决方案是找到具有更大资源的队列或在提交中定义更大的资源需求。
您可能还想回顾man ulimit
虽然我不记得ulimit
我Killed
需要它已经有一段时间了。
就我而言,这是发生在 Laravel 队列工作者身上。系统日志没有提到任何杀戮,所以我进一步查看,结果发现worker基本上是因为超过内存限制(默认设置为128M)的作业而自我杀戮。
运行队列工作者--timeout=600
并--memory=1024
为我解决了问题。
我们在客户站点(我认为是 Red Hat)在 Linux 下遇到了反复出现的问题,OOMKiller(内存不足的杀手)杀死了我们的主要应用程序(即服务器存在的原因)和它的数据库进程。
在每种情况下,OOMKiller 都只是简单地确定进程正在使用大量资源……机器甚至不会因为缺乏资源而发生故障。应用程序和它的数据库都没有内存泄漏(或任何其他资源泄漏)的问题。
我不是 Linux 专家,但我宁愿收集它的算法来决定何时杀死某些东西以及杀死什么是复杂的。另外,有人告诉我(我不能说这句话的准确性)OOMKiller 被嵌入到内核中,你不能简单地不运行它。
用户有能力杀死自己的程序,使用 kill 或 Control+C,但我得到的印象不是发生了什么,并且用户向你抱怨。
root 当然有能力杀死程序,但是如果有人在你的机器上拥有 root 并且正在杀死东西,那么你就有更大的问题。
如果您不是系统管理员,系统管理员可能已经设置了 CPU、RAM 或磁盘使用配额,并自动终止超过这些配额的进程。
除了这些猜测之外,如果没有有关该程序的更多信息,我不确定。
我最近遇到了这个问题。最后,我发现我的进程在 Opensuse zypper update 被自动调用后就被杀死了。禁用 zypper update 解决了我的问题。