1. 概要

Linuxをデフォルト設定で使用すると、メモリをオーバーコミットします。 一方では、これによりリソース使用率が向上します。 一方、これは危険であり、アプリケーションによって直接制御することはできません。 そのため、エラーを軽減するのではなく、分析と回復を実装する必要があります。

2. システムはOOMエラーを報告しましたか?

さまざまなポリシーを使用してメモリを割り当てるようにLinuxを構成できます。 proc ファイルシステムをマウントし、 / proc / sys / vm / から読み取ることで、効果的なポリシーを見つけることができます。 ファイルovercommit_ratioおよびovercommit_memoryは、物理メモリに支えられていないシステムがコミットできるメモリの量を管理します。

OOM(メモリ不足)キラーは、メモリをオーバーコミットするようにシステムを構成した場合にのみ実行されます。 ただし、システムがオーバーコミットしないようにする場合は、overcommit_memoryを2に設定します。 この場合、システムは total_memory * overcommit_ratio/100をオーバーコミットします。 言い換えれば、 overcommit_memory 2にそして overcommit_ratio 0にすると、OOMキラーは無効になります。

残念ながら、OOMエラーを見つけるためにログに依存する必要があります。 Linuxには、さまざまなロギングツールの動物園があります。 この記事では、journaldを使用してシステムログを調べます。 journald は、 syslog インターフェイスを使用して、通常は procファイルシステムのファイル/proc /kmsgからカーネルイベントに関する情報を読み取ります。

このファイルを読み取るもう1つの人気のあるプログラムは、dmesgです。 journald を使用します。これは、 dmesg とは異なり、システムの再起動後も情報を利用できるようにするためです。

3. ログを見つける

journald は、システムログの収集と保存を担当するデーモンです。 それを制御するための姉妹プログラムjournalctlがあります。 journald 構造化ログを保存するため、 journalctl には、それらをすばやくふるいにかけるためのツールがたくさんあります。

3.1. 非対話型の使用

OOMキラーによって強制終了されたプロセスのプロセスIDとプログラム名を見つけたい場合は、次のコマンドを実行できます。

journalctl --list-boots | \
    awk '{ print $1 }' | \
    xargs -I{} journalctl --utc --no-pager -b {} -kqg 'killed process' -o verbose --output-fields=MESSAGE

そしてそれは次のようなものを出力するかもしれません:

Sun 2021-06-20 18:49:15.791688 UTC [s=f81666ba69664fb88b545f20e7a3eea6;i=4dc1ac1;b=b7a40e823b4a4bd0bdf9d
f5fc0dd9b10;m=92c6bf1db5;t=5c537037a9548;x=18ca447c19414dd8]
    MESSAGE=Killed process 3029 (Web Content) total-vm:10206696kB, anon-rss:6584572kB, file-rss:0kB, shm
em-rss:8732kB
Tue 2021-07-06 08:58:35.087345 UTC [s=bc64b16638964d46b0df6e203765c3f7;i=4dd75a3;b=20f10519157b4f1a9b244
352ffdb9577;m=5d93e0be98;t=5c670a08259f1;x=ca08824178edc0de]
    MESSAGE=Killed process 131641 (bash) total-vm:11257404kB, anon-rss:11243152kB, file-rss:12kB, shmem-
rss:0kB

使用したjournalctlコマンドオプションを詳しく見てみましょう。

  • –utc は、journalctlに日付をUTCに変換するように指示します。 これは、クロックにアクセスできない他のシステムからインポートされたsystemdログを処理する場合に特に便利です。 そうでなければ、地理的に多様なシステムを扱うことは非常に困難になります
  • -b は、特定のシステムブートに関連付けられたログを選択します。 1回の呼び出しで複数のブーツを選択する方法はありません。 残念ながら、再起動または一連の再起動でさえ、OOMエラーが発生することがよくあります
  • -k は、 _TRANSPORT =kernelを使用してログメッセージをフィルタリングします。 つまり、カーネルイベントをフィルタリングします
  • -q は、journalctlにログ表示に関連する技術情報を省略するように指示します。 これは、OOM関連のイベントを検索するスクリプトで役立ちます
  • -g は、Emacsでの検索と同様の方法で正規表現検索を実行します。 式に大文字が含まれていない場合、大文字と小文字は区別されないと見なされます
  • –list-boots は、journalctlにログがあるすべてのブーツを出力します
  • -o verboseは、メッセージに関連付けられたフィールドのフィルターされたリストを出力するようにjournalctlに指示します。 または、 -o json を使用することもできます。これにより、ログ集約システムでさらに処理するためのJSON出力が生成されます。
  • –output-fields は、印刷されるフィールドのコンマ区切りのリストです。 journalctl は、一部のフィールドを無条件に出力します。 特に興味深いのは、日付の後に角かっこで囲まれているものです。 括弧内の式はカーソルを指定します。 後でカーソルに-cオプションを指定して、この場所のログを開くことができます

さらに、xargs-Iオプションを使用して、awkによって出力されたビルド番号を最後のjournalctl呼び出しに置き換えました。

3.2. インタラクティブな使用

非対話型の例では、貴重な情報はほとんど出力されません。 アラートをトリガーするために使用される場合がありますが、インシデントを分析するのに十分ではありません。 エラーを報告したシステムにアクセスできるようになったら、そのログをさらに詳しく調べる必要があります。

OOMログのインタラクティブな調査を開始するには、次のようにjournalctlを起動します。

$ journalctl --utc -b -X -ke

X は整数である必要があります(マイナス記号はオプション構文ではなくリテラル整数の一部です)。 journalctl は、負の整数を最後の起動から逆方向にカウントするものとして解釈し、正の整数は最初の起動から順方向にカウントするものとして解釈します。

インタラクティブモードのナビゲーションコマンドは、lessキーバインディングを使用します。

-e オプションは、ポケットベルをログの最後に早送りします。 次に、たとえば「?」と入力して、使用可能な検索コマンドの1つを使用します。 続いて「Killed」。 カーソルが目的のエラーメッセージに移動したら、もう一度「Mem-info」を検索できます。これにより、ログがOOM killerが実行されたときの仮想メモリの状態の概要に巻き戻され、その後にリストが表示されます。プロセスとそのメモリ使用量の統計。

4. journald代替案

一部のLinuxシステムはjournaldを使用しません。 Linuxでシステムログを管理するための一般的なツールはrsyslogdです。 このツールには、豊富なモジュールシステムと多数の構成言語があります。 ただし、 rsyslog のすべての機能をカバーするには、かなりの労力が必要です。 rsyslog 構成へのエントリポイントは、ファイル/etc/rsyslog.confです。 さらに、通常は /etc/rsyslog.dディレクトリが付属しており、構成ファイルが追加されます。

4.1. rsyslogd構造

概念的には、rsyslogは次の種類のモジュールで構成されています。

  • 入力(モジュール名は「im」で始まります。たとえば、任意のファイルからログを読み取るための imflie
  • 出力(モジュール名は「om」で始まります。たとえば、MySQLデータベースにログを保存する場合は ommysql
  • パーサー(モジュール名は「pm」で始まります。たとえば、繰り返しメッセージを処理する場合は pmlastmsg
  • より多くの技術的機能を提供するモジュールタイプは他にもいくつかあります。

4.2. rsyslog構成

rsyslog 構成のいくつかの一般的なパターン、特にOOM関連のメッセージを見つけるのに役立つ可能性のあるパターンを見てみましょう。 カーネルメッセージを照合するための構成ルールは、通常、次のようになります。

kern.*				-/var/log/kern.log

これにより、 rsyslog に、カーネルからのメッセージを/var/log/kern.logというファイルに保存するように指示されます。 このファイルが長すぎる場合、 rsyslog は通常、ファイルをローテーションしてアーカイブします。 続いて、 zgrep は、これらのファイルから読み取るのに役立ちます。

$ find /var/log -name kern* -exec grep -PnHe 'Killed process' {} + 2>

表示される出力の例を次に示します。

/dev/null/var/log/kern.log:5207:Jul  6 11:58:34 cheetah kernel: [401912.220043] Killed process 131641 (bash) total-vm:11257404kB, anon-rss:11243152kB, file-rss:12kB, shmem-rss:0kB

アーカイブされたログの場合:

$ find /var/log -name kern*.gz -exec zgrep -PnHe 'Killed process' {} + 2>/dev/null

次のような出力が表示されます。

/var/log/kern.log.3.gz:1967:Jun 13 14:41:02 cheetah kernel: [347531.586344] Killed process 98254 (chrome) total-vm:889684kB, anon-rss:113068kB, file-rss:0kB, shmem-rss:1784kB
/var/log/kern.log.3.gz:2861:Jun 13 14:41:22 cheetah kernel: [347551.430284] Killed process 102503 (chrome) total-vm:911152kB, anon-rss:104748kB, file-rss:0kB, shmem-rss:1968kB
/var/log/kern.log.3.gz:3781:Jun 13 14:41:52 cheetah kernel: [347582.087504] Killed process 96187 (chrome) total-vm:873296kB, anon-rss:103512kB, file-rss:0kB, shmem-rss:4540kB
/var/log/kern.log.2.gz:1593:Jun 20 21:49:15 cheetah kernel: [630398.445681] Killed process 3029 (Web Content) total-vm:10206696kB, anon-rss:6584572kB, file-rss:0kB, shmem-rss:8732kB

rsyslog のモジュラー構造は、呪いと祝福の両方です。 優れた柔軟性の結果として、データが送信される可能性のある多数の保管場所が生まれます。 いくつか例を挙げると、一元化されたログコレクター、ローカルデータベースサーバー、または単に疑似端末に送信される場合があります。

もちろん、ロガーの選択肢は、journaldおよびrsyslogdよりもはるかに多くなります。 カーネルイベントをログに記録する可能性のあるすべてのプログラムを見つけるために、を試してみてください。

$ sudo lsof | grep /dev/kmsg

これにより、このファイルを読み取っているすべてのプログラムが一覧表示され、場合によっては、その内容がどこかに保存されます。

5. 結論

この記事では、オペレーティングシステムがOOMエラーに関する情報を保存する方法と、最近のOOMエラーに関する情報を探す場所について説明しました。