1. 概要

Linuxシステムを使用する場合、最終的にはプロセスを停止した理由とその理由を解明する必要があります。この記事では、そのトラブルシューティング方法について説明します。

Linuxでプロセスがどのように終了するかを理解することから始めます。 次に、カーネルがプロセスを強制終了することを決定したときの関連ログの場所を示します。 最後に、その手順が開始された理由を調べます。

2. プロセスがどのように終了するかを理解する

Linuxでプロセスを終了する方法は一般に2つあります。

  • 自発的に: exit()システム呼び出しを呼び出します。 これは、プロセスがタスクを終了したことを意味するため、終了することを選択します。
  • 思わず:信号を受信したとき。 このシグナルは、別のユーザー、別のプロセス、またはLinux自体によって送信される可能性があります。

ここでは後者の場合に焦点を当て、信号とは何か、およびそれらがどのように機能するかを確認します。 次に、プロセスの終了に関連するシグナルについて説明します。

2.1. Linuxシグナルの紹介

信号は、Linuxでプロセス間通信(IPC)を実行する方法の1つです。 プロセスがシグナルを受信すると、通常の実行パスを停止します。その特定のシグナルを明示的に無視しない限り、プロセスはそれぞれのシグナルハンドラーを実行します。

このシグナルハンドラーは、特定のシグナルを受信したときにプロセスが何をすべきかを指示する小さなルーチンです。 プロセスは、それらの1つ以上に対してシグナルハンドラーを定義するか、Linuxが提供するデフォルトハンドラーに便乗するかを選択できます。 後のセクションで説明するように、無視または上書きできないシグナルが1つあります。それは、SIGKILLシグナルです。

2.2. 終了信号

ここで、プロセスの終了に関連する信号について簡単に説明します。

  • SIGTERM:これは、プロセスに終了を要求する「優れた」方法です。つまり、プロセスはいくつかのクリーンアップ操作を実行し、正常にシャットダウンできます。
  • SIGINT:ユーザーがINTR文字(CTRL + c)を送信してプロセスを中断したことを示します。
  • SIGQUIT:SIGTERMと似ていますが、終了プロセス中にコア・タンプも生成する点が異なります。
  • SIGHUP:これは、ユーザーの端末が何らかの理由で切断されていることを示します。
  • SIGKILL:この特別なシグナルは無視したり処理したりすることはできず、すぐにプロセスを強制終了します。

次のセクションでは、SIGKILLについて簡単に説明します。これは、Linuxが必要なときにプロセスを終了する方法です。

2.3. SIGKILLシグナル

プロセスがSIGKILLを受信すると、弾丸が来るのを聞くことができません。 SIGTERMやSIGQUITとは異なり、 SIGKILLを別の方法でブロックまたは処理することはできません。 そのため、プロセスをすぐに終了する必要がある場合の最後の手段と見なされることがよくあります。

プロセスを終了しようとするときの一般的な方法は、最初にSIGTERMまたはSIGQUITを試してみて、妥当な時間が経過しても停止しない場合は、SIGKILLを介して強制的に実行することです。

後のセクションで説明するように、LinuxはSIGKILLをプロセスに送信して、オペレーティングシステムがリソースの使用に苦労しているときに即時終了を強制する場合もあります。

3. 誰がプロセスを殺したかを知る

プロセスがどのように強制終了されるかを確認したので、プロセス終了の根本的な原因を調べて、プロセスに関する詳細情報を見つけることができます。

プロセスが自発的に終了しなかったと仮定すると、プロセスを終了できる唯一の方法は、前述のシグナルを使用することです。 これらの信号は、別のプロセスまたはLinuxカーネルのいずれかによって送信できます。 次のセクションでは両方のシナリオを検討しますが、カーネルが開始するプロセスの終了に焦点を当てます。

3.2. 開始信号の処理

多くの場合、他のユーザーまたはプロセスがプロセスを強制終了することを選択する場合があります。 前に説明したように、これは最終的にSIGTERMまたはSIGKILLシグナル(または両方の組み合わせ)を介して発生します。

pkillコマンドでプロセスを停止するユーザーの例を次に示します。

最初にターミナルを開き、20秒間スリープする新しいプロセスを作成します。

$ sleep 20

次に、別の端末から:

$ pkill sleep

最後に、最初のターミナルに戻ると、次のようになります。

$ sleep 20
Terminated

このTerminatedメッセージがあり、プロセスが終了したことを示していることに注意してください。 ただし、プロセスが端末でアクティブでない場合(たとえば、ユーザーがグラフィカルユーザーインターフェイスまたは cron ジョブからプロセスを開始したため)、何が起こったのかを理解するのがより困難になります。 。 したがって、この種のユーザーアクティビティを監視するには、事前に設定する必要があります。 pssactauditdなどのツールは、それを実現するのに役立ちます。

3.3. カーネルが開始する信号

Linuxカーネルは、システムのリソースが不足しているときに1つ以上のプロセスを終了することも決定する場合があります。 その非常に一般的な例は、システムの物理メモリが使い果たされたときにアクションを実行するメモリ不足(OOM)キラーです。

このイベントが発生すると、カーネルは関連情報をカーネルログバッファーに記録します。カーネルログバッファーは / dev / kmsgから利用できます。いくつかのツールを使用すると、その仮想デバイスからの読み取りが簡単になります。最も人気のあるのはdmesgjournalctlです。 いくつかの例を見てみましょう。

まず、OOMキラーをトリガーしましょう。

$ (echo "li = []" ; echo "for r in range(9999999999999999): li.append(str(r))") | python
Killed

それでは、dmesgを使用して関連するログを調べてみましょう。

$ sudo dmesg | tail -7
[427918.962500] [ 142394] 1000 142394 58121 2138 335872 0 0 Socket Process
[427918.962505] [ 179856] 1000 179856 660680 21527 1208320 0 0 Web Content
[427918.962508] [ 179902] 1000 179902 605502 3489 483328 0 0 Web Content
[427918.962510] [ 179944] 1000 179944 3197660 3175506 25534464 0 0 python
[427918.962514] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,
global_oom,task_memcg=/user.slice/user-1000.slice/session-2.scope,task=python,pid=179944,uid=1000
<strong>[427918.962531] Out of memory: Killed process 179944 (python) total-vm:12790640kB, anon-rss:12702024kB,</strong>
file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:24936kB oom_score_adj:0
[427919.411464] oom_reaper: reaped process 179944 (python), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

journalctlを使用してログを調査することもできます。

$ journalctl --list-boots | \
    awk '{ print $1 }' | \
    xargs -I{} journalctl --utc --no-pager -b {} -kqg 'killed process' -o verbose --output-fields=MESSAGE
Fri 2021-12-10 17:49:55.782801 UTC [s=38b35d6842d24a09ab14c8735cd79ff7;i=aeef;b=cd40ed63d47d4814b4c2c0f9ab73341f;m=63a20e170d;t=5d2ce59d50891;x=cdd950f6be42011b]
<strong>    MESSAGE=Out of memory: Killed process 179944 (python) total-vm:12790640kB, anon-rss:12702024kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:24936kB oom_score_adj:0</strong>

4. メモリ不足のキラー

このセクションでは、OOMキラーとその基礎となるメカニズムについて簡単に触れます。

Linuxにはこの仮想メモリの概念があります。つまり、各プロセスの観点から、コンピュータ全体の物理メモリ全体を使用できます。 これにより、メモリのオーバーコミットが可能になるため、プログラミングが非常に簡単になります。 これにより、別のプロセスがすでに使用可能なメモリを要求している場合でも、各プロセスがより多くのメモリスペースをすばやく取得できるようになります。 ただし、すべてのプロセスが同じメモリスペースを同時に使用しようとすると、整合性の問題が発生します。 ここで、OOMキラーが登場します。

OOMキラーの仕事は、システムのメモリが不足しているときに最小数のプロセスを選択し、それらを終了することです。 悪さのスコアを使用します– を通じて利用可能です procfs 経由 / proc / / oom_score – 強制終了するプロセスを決定します。 その決定を行う間、それはそれを確実にすることによって損害を最小にしようとします:

  • 失われた作業を最小限に抑えます
  • 可能な限り多くのメモリを回復します
  • 罪のないプロセスを殺すのではなく、大量のメモリを消費するプロセスだけを殺します
  • 強制終了されるプロセスの数を最小限に抑えます(理想的には1つだけ)
  • ユーザーが期待するプロセスを強制終了します

必要に応じてOOMキラーをカスタマイズするために使用できるパラメーターは他にもたくさんあります。

5. 結論

この記事では、Linuxプロセスを強制終了した原因と、これが発生した理由を確認する方法を説明しました。 次に、プロセス終了の最も一般的なシグナルを確認しました。 次に、Linuxカーネルがプロセスを強制終了する方法について説明しました。 最後に、OOMキラーの基本に触れました。