Điều gì đã giết quá trình của tôi và tại sao?


614

Ứng dụng của tôi chạy như một quá trình nền trên Linux. Nó hiện đang được bắt đầu tại dòng lệnh trong cửa sổ Terminal.

Gần đây, một người dùng đã thực thi ứng dụng này một thời gian và nó đã chết một cách bí ẩn. Văn bản:

Bị giết

đã ở trên thiết bị đầu cuối. Điều này đã xảy ra hai lần. Tôi hỏi nếu ai đó ở Terminal khác sử dụng lệnh kill để giết tiến trình? Không.

Trong những điều kiện nào Linux sẽ quyết định giết quá trình của tôi? Tôi tin rằng cái vỏ hiển thị "bị giết" bởi vì quá trình đã chết sau khi nhận được tín hiệu kill (9). Nếu Linux gửi tín hiệu kill thì sẽ có một thông báo trong nhật ký hệ thống ở đâu đó giải thích tại sao nó bị giết?


23
linux đã giết quá trình của tôi và đăng nhập nó vào / var / log / message trên redhat
Dean Hiller

1
Xem thêm câu trả lời này trên unix.stackexchange.com.
Richard

Có 3 người chơi trong sự kiện này: (1) Quá trình (nguyên nhân chung) chiếm quá nhiều bộ nhớ và gây ra tình trạng OOM (2) Hạt nhân gửi SIGKILL (tín hiệu 9) để chấm dứt nó và ghi lại sự thật trong một số hệ thống log like /var/log/messages(3) Shell trong đó tiến trình chạy là quá trình in Killedthông báo khi trạng thái thoát từ waitpid(2)biểu thị tiến trình con đã chết từ tín hiệu 9.
arielf

Sau khi đọc câu trả lời của @ DeanHiller, tôi đã tìm thấy các thông điệp /var/log/syslog
tường trình

Câu trả lời:


403

Nếu người dùng hoặc sysadmin không giết chương trình thì kernel có thể có. Hạt nhân sẽ chỉ giết một quá trình trong các trường hợp đặc biệt như đói tài nguyên cực độ (nghĩ rằng mem + cạn kiệt trao đổi).


25
Nếu kernel giết tiến trình, nó sẽ đặt một thông điệp vào một bản ghi ở đâu đó?
sbq

186
Tôi vừa viết một chương trình mà bộ nhớ malloc'd trong một vòng lặp không liên tục. Sau khi hệ thống bị chậm, "Bị giết" được hiển thị trong thiết bị đầu cuối và quá trình này bị chấm dứt. Tệp /var/log/kern.log chứa rất nhiều thông tin về việc chấm dứt. -Cảm ơn cho con trỏ.
sbq

6
Đó gần như chắc chắn là nó. Tôi đã thấy điều này rất nhiều khi TAing. Nhiều sinh viên sẽ quên giải phóng các đối tượng của họ và các ứng dụng cuối cùng sẽ đạt tới 3GB sử dụng bộ nhớ ảo. Ngay khi nó chạm vào điểm đó, nó đã bị giết.
Herms

8
Khi "chương trình đơn giản gặp sự cố", đó hệ điều hành thực sự giết chết quá trình!
Bernd Jendrissek

79
Sử dụng dmesgđể xem nhật ký kernel: ở đây tôi thấy các quá trình python của mình bị kernel giết chết do tiêu thụ bộ nhớ ảo quá cao.
caneta

273

Thử:

dmesg -T| grep -E -i -B100 'killed process'

Trường hợp -B100biểu thị số lượng dòng trước khi giết xảy ra.

Bỏ qua -T trên Mac OS.


6
FYI, từ info egrep: "egrep giống như grep -E. ... Gọi trực tiếp như egrep hoặc fgrep không được chấp nhận"
Air

9
Trong trường hợp một mẫu đơn giản như 'killed process'bạn chỉ có thể sử dụng grepthay vì egrepkhông có thay đổi nào khác. Đối với một mẫu phức tạp hơn, bạn sẽ thay đổi thay thế, ví dụ như egrep -i -B100 'foo|ba[rz]'với grep -E -i -B100 'foo|ba[rz]'. Q & A này cung cấp thêm chi tiết.
Không khí

2
Tôi cũng đề nghị sử dụng dmesg -Tđể có được dấu thời gian có thể đọc được
gukoff

171

Đây trông giống như một bài viết hay về chủ đề: thuần hóa kẻ giết người OOM .

Ý chính là Linux quá mứcký ức. Khi một tiến trình yêu cầu thêm dung lượng, Linux sẽ cung cấp cho nó khoảng trống đó, ngay cả khi nó được yêu cầu bởi một tiến trình khác, với giả định rằng không ai thực sự sử dụng tất cả bộ nhớ mà họ yêu cầu. Quá trình sẽ được sử dụng độc quyền bộ nhớ mà nó đã phân bổ khi nó thực sự sử dụng nó, chứ không phải khi nó yêu cầu. Điều này giúp phân bổ nhanh chóng và có thể cho phép bạn "gian lận" và phân bổ nhiều bộ nhớ hơn mức bạn thực sự có. Tuy nhiên, một khi các quy trình bắt đầu sử dụng bộ nhớ này, Linux có thể nhận ra rằng nó đã quá hào phóng trong việc phân bổ bộ nhớ mà nó không có và sẽ phải loại bỏ một quy trình để giải phóng một số. Quá trình bị giết dựa trên điểm số có tính đến thời gian chạy (các quy trình chạy dài sẽ an toàn hơn), sử dụng bộ nhớ (các quy trình tham lam ít an toàn hơn) và một vài yếu tố khác, bao gồm một giá trị bạn có thể điều chỉnh để làm cho quá trình ít bị giết hơn. Tất cả được mô tả trong bài viết chi tiết hơn rất nhiều.

Chỉnh sửa: Và đây là một bài viết khác giải thích khá rõ cách thức một quy trình được chọn (chú thích với một số ví dụ mã hạt nhân). Điều tuyệt vời về điều này là nó bao gồm một số bình luận về lý do đằng sau các badness()quy tắc khác nhau .


3
Tôi thực sự thích các liên kết bài viết. Tôi muốn đề nghị bất cứ ai quan tâm đến chủ đề này nên đọc chúng - đặc biệt là các bình luận về bài viết lwn.
Jon Bringhurst

4
"Linux sẽ cung cấp cho nó không gian đó, ngay cả khi nó được yêu cầu bởi một quy trình khác" Đó không hoàn toàn là cách bộ nhớ ảo hoạt động ...
Mooing Duck

1
bài viết khá cũ (2009) và không phải tất cả các chức năng được đề xuất trong bài viết đều nằm trong dòng chính.
Alex

50

Trước tiên hãy để tôi giải thích khi nào và tại sao OOMKiller được gọi?

Giả sử bạn có 512 RAM + 1GB Bộ nhớ hoán đổi. Vì vậy, về lý thuyết, CPU của bạn có quyền truy cập vào tổng số 1,5 GB bộ nhớ ảo.

Bây giờ, đôi khi mọi thứ đều chạy tốt trong vòng 1,5 GB tổng bộ nhớ. Nhưng đột nhiên (hoặc dần dần) hệ thống của bạn đã bắt đầu tiêu thụ ngày càng nhiều bộ nhớ và nó đạt đến điểm khoảng 95% tổng bộ nhớ được sử dụng.

Bây giờ nói rằng bất kỳ quá trình đã yêu cầu một lượng lớn bộ nhớ từ kernel. Kiểm tra hạt nhân cho bộ nhớ khả dụng và thấy rằng không có cách nào nó có thể phân bổ quá trình của bạn thêm bộ nhớ. Vì vậy, nó sẽ cố gắng giải phóng một số bộ nhớ gọi / gọi OOMKiller ( http://linux-mm.org/OOM ).

OOMKiller có thuật toán riêng để ghi thứ hạng cho mọi quy trình. Thông thường, quá trình sử dụng nhiều bộ nhớ sẽ trở thành nạn nhân bị giết.

Tôi có thể tìm thấy nhật ký của OOMKiller ở đâu?

Thông thường trong thư mục / var / log. Hoặc /var/log/kern.log hoặc / var / log / dmesg

Hy vọng điều này sẽ giúp bạn.

Một số giải pháp điển hình:

  1. Tăng bộ nhớ (không trao đổi)
  2. Tìm rò rỉ bộ nhớ trong chương trình của bạn và sửa chúng
  3. Hạn chế bộ nhớ mà bất kỳ quá trình nào cũng có thể tiêu thụ (ví dụ: bộ nhớ JVM có thể bị hạn chế khi sử dụng JAVA_OPTS)
  4. Xem nhật ký và google :)

17

Đây là Linux hết bộ quản lý bộ nhớ (OOM) . Quá trình của bạn đã được chọn do " tính xấu " - sự kết hợp của độ gần đây, kích thước lưu trú (bộ nhớ đang sử dụng, thay vì chỉ được phân bổ) và các yếu tố khác.

sudo journalctl -xb

Bạn sẽ thấy một thông báo như:

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

12

Như dwc và Adam Jaskiewicz đã tuyên bố, thủ phạm có khả năng là OOM Killer. Tuy nhiên, câu hỏi tiếp theo là: Làm thế nào để tôi ngăn chặn điều này?

Có một số cách:

  1. Cung cấp cho hệ thống của bạn nhiều RAM hơn nếu bạn có thể (dễ dàng nếu là VM)
  2. Hãy chắc chắn rằng kẻ giết người OOM chọn một quy trình khác.
  3. Vô hiệu hóa OOM Killer
  4. Chọn một bản phân phối Linux đi kèm với OOM Killer bị vô hiệu hóa.

Tôi thấy (2) đặc biệt dễ thực hiện, nhờ vào bài viết này .


2
Đó là RAM cho tôi. Tôi đã nâng cấp từ 2 lên 4GB RAM và vấn đề đã biến mất. Bây giờ vấn đề là với hóa đơn: P
Gus

9

Các mô-đun PAM với các nguồn lực giới hạn gây ra kết quả chính xác bạn mô tả: Quá trình của tôi qua đời một cách bí ẩn với các văn bản bị giết trên cửa sổ giao diện điều khiển. Không có đầu ra nhật ký, không trong syslog cũng như trong kern.log . Các đầu chương trình đã giúp tôi khám phá ra rằng chính xác sau một phút sử dụng CPU quá trình của tôi bị giết.


8

Một công cụ như systemtap (hoặc một bộ theo dõi) có thể giám sát logic và báo cáo truyền tín hiệu hạt nhân. ví dụ: https://sourceware.org/systemtap/examples/ Process / sigmon.stp

# stap .../sigmon.stp -x 31994 SIGKILL
   SPID     SNAME            RPID  RNAME            SIGNUM SIGNAME
   5609     bash             31994 find             9      SIGKILL

Khối lọc iftrong tập lệnh đó có thể được điều chỉnh theo sở thích hoặc loại bỏ để theo dõi lưu lượng tín hiệu toàn hệ thống. Nguyên nhân có thể được phân lập thêm bằng cách thu thập backtraces (thêm a print_backtrace()và / hoặc print_ubacktrace()vào đầu dò, cho kernel- và không gian người dùng - tương ứng).


4

Trong môi trường lsf (tương tác hoặc cách khác) nếu ứng dụng vượt quá mức sử dụng bộ nhớ vượt quá ngưỡng cài đặt trước của quản trị viên trên hàng đợi hoặc yêu cầu tài nguyên gửi đến hàng đợi, các quy trình sẽ bị hủy để người dùng khác không trở thành nạn nhân tiềm năng chạy trốn. Nó không luôn gửi email khi làm như vậy, tùy thuộc vào cách thiết lập.

Một giải pháp trong trường hợp này là tìm một hàng đợi có tài nguyên lớn hơn hoặc xác định các yêu cầu tài nguyên lớn hơn trong bài nộp.

Bạn cũng có thể muốn xem lại man ulimit

Mặc dù tôi không nhớ ulimitkết quả Killedlà đã được một thời gian kể từ khi tôi cần điều đó.


2

Chúng tôi đã gặp sự cố tái diễn trong Linux tại một trang web của khách hàng (Red Hat, tôi nghĩ vậy), với OOMKiller (kẻ giết người hết bộ nhớ) giết chết cả ứng dụng chính của chúng tôi (tức là lý do máy chủ tồn tại) và đó là quy trình cơ sở dữ liệu.

Trong mỗi trường hợp, OOMKiller chỉ đơn giản quyết định rằng các quy trình đang sử dụng nhiều tài nguyên ... máy thậm chí còn không bị lỗi vì thiếu tài nguyên. Cả ứng dụng và cơ sở dữ liệu của nó đều không có vấn đề với rò rỉ bộ nhớ (hoặc bất kỳ rò rỉ tài nguyên nào khác).

Tôi không phải là một chuyên gia về Linux, nhưng tôi tập hợp thuật toán của nó để quyết định khi nào nên giết một cái gì đó và cái gì để giết là phức tạp. Ngoài ra, tôi được cho biết (tôi không thể nói chính xác về điều này) rằng OOMKiller được đưa vào Kernel và bạn không thể đơn giản chạy nó.


1
IIRC, OOMKiller chỉ được gọi là phương sách cuối cùng. Tôi nghĩ hệ thống thậm chí sẽ gửi tín hiệu đến các ứng dụng khác nhau yêu cầu họ vui lòng từ bỏ một số tài nguyên trước khi buộc phải gọi OOMKiller. Mang theo một hạt muối, vì đó là một thời gian dài ...
rmeador

1
Bạn chỉ có thể không chạy nó. Nó được nướng vào kernel, nhưng có các tùy chọn để điều chỉnh cách nó chạy, và thậm chí cả quá trình mà nó có khả năng bị giết. Nó chạy khi toàn bộ hệ thống hết bộ nhớ, không phải khi một quy trình cụ thể đang sử dụng quá nhiều. Xem câu trả lời của tôi để biết thêm chi tiết.
Adam Jaskiewicz

6
Không chạy oomkiller là khá dễ dàng. echo "2" > /proc/sys/vm/overcommit_memory
R .. GitHub DỪNG GIÚP ICE

Red Hat không muốn cho phép nó được thay đổi: sudo echo "2" > /proc/sys/vm/overcommit_memory/ Proc / sys / vm / overcommit_memory: Quyền bị từ chối
Brent Faust

2
Hãy thửecho 2 | sudo tee /proc/sys/vm/overcommit_memory
Hypershadsy 12/2/2015

2

Trong trường hợp của tôi, điều này đã xảy ra với một nhân viên xếp hàng của Laravel. Nhật ký hệ thống không đề cập đến bất kỳ sự giết chóc nào nên tôi nhìn xa hơn và hóa ra công nhân về cơ bản là tự sát vì một công việc vượt quá giới hạn bộ nhớ (được đặt thành 128M theo mặc định).

Chạy nhân viên xếp hàng với --timeout=600--memory=1024sửa lỗi cho tôi.


0

Người dùng có khả năng tự hủy các chương trình của mình, sử dụng kill hoặc Control + C, nhưng tôi có ấn tượng rằng đó không phải là điều đã xảy ra và người dùng đã phàn nàn với bạn.

root có khả năng giết chương trình tất nhiên, nhưng nếu ai đó có root trên máy của bạn và đang giết thứ bạn có vấn đề lớn hơn.

Nếu bạn không phải là sysadmin, sysadmin có thể đã thiết lập hạn ngạch trên CPU, RAM, sử dụng đĩa và tự động giết các quá trình vượt quá chúng.

Khác với những dự đoán đó, tôi không chắc chắn nếu không có thêm thông tin về chương trình.


6
CTRL-C gửi lệnh giết khác với OP đã báo cáo (SIGINT (2) khi tôi nhớ lại, trong khi chương trình đang nhận SIGKILL (9)).
Powerlord

0

Tôi đã gặp vấn đề này gần đây. Cuối cùng, tôi thấy các quy trình của mình đã bị giết ngay sau khi cập nhật Opensuse zypper được gọi tự động. Để vô hiệu hóa cập nhật zypper đã giải quyết vấn đề của tôi.


Tôi đang thấy vấn đề tương tự. Làm thế nào bạn theo dõi quá trình nào đã giết chết quá trình của bạn? Có vẻ như có một công cụ để kiểm tra ai gửi SIGKILL đến một quy trình.
Howy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.