Kexec は現在動作中のカーネルから他のカーネルを高速に起動するための仕組みです。これにより、ハードウエアの初期化を行わず、高速にシステムを再起動することができます。必要であれば、システムがクラッシュした際、もう 1 つのカーネルを起動することもできます。
Kexec を使用することで、ハードウエアによる再起動を行うことなく、別のカーネルを起動することができるようになります。このツールは、下記のような用途で使用されます:
高速な再起動
システムを頻繁に再起動する必要があるような場合、 Kexec は時間をかなり削減できるようになります。
不正なファームウエアやハードウエアの回避
コンピュータのハードウエアは複雑な構造であり、システムの起動時に深刻な問題が発生する場合があります。このような場合、すぐにハードウエアを交換できればよいのですが、そうは行かない場合があります。 Kexec では、ハードウエアの初期化が完了した状態から、特定の制御環境下に移行することができます。これにより、システムの起動が失敗するようなリスクを抑えることができます。
カーネルがクラッシュした際のダンプの保存
Kexec は物理メモリ内の情報を保持して動作します。そのため、 本番用 のカーネルに何らかの障害が発生した場合、 情報採取用 のカーネル (限られたメモリ範囲内だけで動作する追加のカーネル) を起動することで、障害情報を保存することができるようになります。保存されたイメージは、後から解析用に使用することができます。
GRUB 2 の設定を使用しない起動
Kexec 経由でカーネルを起動した場合、ブートローダの段階は省略されます。通常はブートローダの設定が誤っていると、起動の処理を行うことができなくなりますが、 Kexec を使用することで、ブートローダの設定に依存せずに起動することができるようになります。
openSUSE® Leap で Kexec を使用すると、再起動を高速化したり潜在的なハードウエア問題を回避したりすることができます。 Kexec を使用するには、 kexec-tools
パッケージをインストールしてください。このパッケージには kexec-bootloader
というスクリプトが含まれていますが、これはブートローダの設定からカーネルのコマンドラインオプションを読み出し、そのコマンドラインオプションを利用して新しいカーネルを起動することができます。
カーネルのクラッシュ時にデバッグ情報を取得する環境を設定したい場合は、 makedumpfile
パッケージをインストールしておいてください。
openSUSE Leap での Kdump の使用方法は、 YaST の Kdump モジュールで設定することができます。 YaST モジュールを使用する場合は、 yast2-kdump
パッケージをインストールしておいてください。
Kexec で最も重要なコンポーネントは /sbin/kexec
です。 Kexec でカーネルを読み込む際、 2 種類の方法で行うことができます:
通常の再起動と同様に、本番用のカーネルのアドレス領域にカーネルを読み込む方法:
#
kexec
-l
カーネルイメージ
読み込んだあと、そのカーネルを実行するには、 kexec
-e
と入力して実行します。
メモリ内の専用の領域にカーネルを読み込む方法:
#
kexec
-p
カーネルイメージ
このカーネルは、システムがクラッシュした際に自動的に起動されます。
システムがクラッシュした際、本番用のカーネルのデータを保持したまま、もう 1 つのカーネルを起動したい場合は、システムメモリ内に専用の領域を用意する必要があります。その領域は常に空けておかなければならないものであることから、この専用領域には本番用のカーネルが読み込まれることはありません。この領域は情報採取用のカーネルが使用するもので、このような仕組みによって、本番用のカーネルのメモリページを保持させることができるようになっています。
このような領域を予約するには、本番用のカーネルの起動コマンドライン内に、 crashkernel
というオプションを追加します。 crashkernel
で必要な値を判断するには、 18.4項 「crashkernel
割り当てサイズの計算」 に書かれた手順に従ってください。
なお、上記のパラメータは情報採取用のカーネルのパラメータではありません。情報採取用のカーネルでは Kexec を使用しません。
情報採取用のカーネルは専用の領域に読み込まれ、カーネルがクラッシュするのを待ちます。いったんクラッシュが発生すると、 Kdump は情報採取用のカーネルに制御を移します。これは、クラッシュした時点で、元のカーネルは信頼できる状態ではなくなるためです。これはつまり、 Kdump 自身も失敗する可能性があることを示しています。
情報採取用のカーネルを読み込むには、カーネルの起動パラメータを含める必要があります。ほとんどの場合、初期 RAM ファイルシステムを起動時に使用します。初期 RAM ファイルシステムを指定するには、 --initrd
=
ファイル名 のようなオプションを指定します。なお、 --append
=
コマンドライン のように指定すると、起動するほうのカーネルのコマンドラインを設定することができます。
なお、本番用のカーネルで指定していたコマンドラインを含めておく必要があります。このような場合は、 --append
=
"$(cat /proc/cmdline)" のように入力して実行することで、既存のコマンドラインをそのまま受け渡すことができます。また、オプションを追加したい場合は、 --append
=
"$(cat /proc/cmdline) オプション" のようにして追加のオプションを指定してもかまいません。
たとえば、 /boot/vmlinuz-6.4.0-150600.9-default
というカーネルイメージファイルに対して、現在動作中のカーネルに指定しているものと同じ /boot/initrd
ファイルを使用するように指定したい場合は、下記のようなコマンドになります:
#
kexec -l /boot/vmlinuz-6.4.0-150600.9-default \
--append="$(cat /proc/cmdline)" --initrd=/boot/initrd
読み込んでおいたカーネルはいつでも解放することができます。 -l
オプションで読み込んでおいたカーネルを解放したい場合は、 kexec
-u
コマンドを実行してください。また、 -p
オプションで読み込んでおいたカーネルの場合は、 kexec
-p
-u
コマンドを実行してください。
crashkernel
割り当てサイズの計算 #Edit sourceKexec で情報採取用のカーネルを起動する 場合、このカーネル用のメモリ領域を割り当てておく必要があります。割り当てるべきサイズはコンピュータのハードウエア設定によって異なりますので、あらかじめ指定しておく必要があります。
割り当てるべきサイズは、お使いのコンピュータのハードウエアアーキテクチャによっても異なります。それぞれ下記の手順をお読みのうえ、必要なサイズを判断してください。
コンピュータに対する基礎値を得るには、端末内で下記のコマンドを入力し実行します:
#
kdumptool
calibrate Total: 49074 Low: 72 High: 180 MinLow: 72 MaxLow: 3085 MinHigh: 0 MaxHigh: 45824
それぞれの値はメガバイト単位です。
上記の Low
および High
の値を記録しておきます。
Low
と High
の値の意味についてAMD64/Intel 64 コンピュータの場合、 High
は利用可能な全てのメモリを予約する意味になり、 Low
は DMA32 ゾーン内のメモリ (つまり 4 GB 以下の領域) を予約する意味になります。
SIZE_LOW は 32 ビットのみに対応したデバイスで必要なメモリ量を表します。カーネルは DMA32 のバウンスバッファに対して 64M を割り当てますが、お使いのサーバ内に 32 ビットのみに対応したデバイスが存在しない場合は、 SIZE_LOW
の値は既定の 72M で問題なく動作するはずです。ただし、 NUMA マシンの場合は例外で、より多くの Low
が必要となる場合があります。そのため、通常のカーネルの割り当てで Low
メモリを使用しないようにするため、 Kdump カーネルのパラメータに numa=off
を設定してもかまいません。
上記の手順の High
の値に、お使いのコンピュータに接続されている LUN カーネルパス (ストレージデバイスのパス数) を元にした値を足します。具体的には、メガバイト単位で下記のような計算を行います:
SIZE_HIGH = 推奨値 + (LUN_数 / 2)
上記の数式に当てはめるべき値は下記のとおりです:
SIZE_HIGH: High
の計算結果です。
RECOMMENDATION: kdumptool calibrate
で表示された High
の値です。
LUNs: お使いのコンピュータで作成する予定の LUN カーネルパス数の最大値を指定します。マルチパスデバイスについては無視されるため、数から除外してください。お使いのシステムで利用可能な 現在の LUN 数を取得するには、下記のようなコマンドを入力して実行します:
>
cat /proc/scsi/scsi | grep Lun | wc -l
お使いのデバイスに対応するドライバが DMA32 ゾーン内に多数の予約領域を作成する場合は、 Low
の値も調整する必要があります。しかしながら、この値は簡単に計算できるものではありません。正しい値を得るには、試行錯誤を繰り返す必要があります。
まずは Low
の値を kdumptool calibrate
で出力された値から試してみてください。
あとは値を正しい場所に設定します。
お使いのブートローダの設定で、カーネルオプションに下記を追加してください:
crashkernel=SIZE_HIGH,high crashkernel=SIZE_LOW,low
SIZE_HIGH と SIZE_LOW の値は、それぞれ上記の手順で算出もしくは試行錯誤した結果を入力してください。また、末尾には M
(メガバイトの意味です) を付与してください。
たとえば下記のようになります:
crashkernel=36M,high crashkernel=72M,low
Low
の値を入力してください。
High
の値を入力してください。
下記のコマンドを入力して実行してください:
#
yast kdump startup enable alloc_mem=LOW,HIGH
ここで、 LOW には Low
の値を、 HIGH には High
の値をそれぞれ入力してください。
利用可能なデバイスの数にもよりますが、 crashkernel
カーネルパラメータで指定したメモリ量が不足する場合があります。不足した場合は、メモリを増やす代わりに、カーネル側で見えるデバイスの量を制限することができます。これにより、 crashkernel の設定で必要なメモリ量を減らすことができます。
デバイスを無視したい場合は、 cio_ignore
ツールを利用することで、現時点で有効化されているデバイスや使用しているデバイスを除き、それ以外の全てのデバイスを無視する設定を生成することができます。
>
sudo
cio_ignore -u -k cio_ignore=all,!da5d,!f500-f502
cio_ignore -u -k
と入力して実行すると、ブラックリスト設定が即時に有効化され、既存のブラックリストを置き換えるようになります。未使用のデバイスが消えることはなく、チャネルサブシステム内で変わらず現れるようになります。ただし、新しいチャネルデバイスを追加 (z/VM 下での CP ATTACH か、 LPAR での動的な I/O 設定変更) すると、それらはブラックリストとして扱われます。この動作をしないようにするには、まず既存の設定を sudo cio_ignore -l
を実行して保存し、 cio_ignore -u -k
コマンドの実行後にその状態に戻すようにしてください。それ以外の方法としては、生成された設定を通常のカーネルパラメータに追加する方法もあります。
この方法の場合は、 /etc/sysconfig/kdump
内にある KDUMP_CMDLINE_APPEND
の値の中に、 cio_ignore
パラメータを追加してください。たとえば下記のようになります:
KDUMP_COMMANDLINE_APPEND="cio_ignore=all,!da5d,!f500-f502"
設定を反映させるには、 kdump
を再起動します:
systemctl restart kdump.service
Kexec を使用するには、まず対応するサービスを有効化し、動作させる必要があります:
Kexec のサービスをシステムの起動時に開始するようにするには、下記のように入力して実行します:
>
sudo
systemctl enable kexec-load.service
Kexec サービスを開始するには、下記のように入力して実行します:
>
sudo
systemctl start kexec-load.service
お使いの Kexec 環境が正しく動作していることを確認するには、 Kexec を利用して新しいカーネルを起動してください。ただし、お使いのシステム内には誰もログインしていない状態で、重要なサービスを動作させていない状態であることを確認しておいてください。あとは下記のコマンドを入力して実行します:
systemctl kexec
これにより、あらかじめ読み込んでおいた新しいカーネルが古いカーネルを置き換えて、制御を行うようになります。制御が始まると、通常の起動メッセージが表示されます。新しいカーネルが起動しても、ハードウエアやファームウエアのチェックは省略されます。このとき、何も警告メッセージが表示されないことを確認してください。
reboot
コマンドで通常の再起動を行わず、 Kexec を使用するように設定したい場合は、下記のように入力して実行します:
ln -s /usr/lib/systemd/system/kexec.target /etc/systemd/system/reboot.target
なお、 etc/systemd/system/reboot.target
ファイルを削除することで、元の再起動に戻すことができます。
Kexec は定期的な再起動処理でも使用することができます。たとえばハードウエア検出ルーチンに長い時間がかかるような環境や、起動時の信頼性があまり高くないシステムなどで有用です。
ただし、 Kexec でシステムを再起動する際は、ファームウエアやブートローダを使用しないことに注意してください。ブートローダ側で設定を変更していても、物理的な (Kexec を使用しない) 再起動を行うまで、それらは反映されません。
Kdump を使用することで、カーネルのダンプ情報を保存することができます。これは、カーネルがクラッシュしてしまった場合、その時点のメモリ内容をファイルシステムに保存する機能です。この仕組みにより、カーネルがクラッシュした時点で何が起こっていたのかを調べることができるようになります。これを 「コアダンプ」 と呼びます。
Kdump は Kexec と同じ仕組みで動作するものです (詳しくは 第18章 「Kexec と Kdump」 をお読みください) 。この場合、本番用のカーネルがクラッシュした際に、情報採取用のカーネルを起動します。ただし、 Kexec では本番用のカーネルをそのまま置き換えて動作するのに対して、 Kdump ではクラッシュした本番用のカーネルのメモリを保持し続ける点が異なります。これにより、 Kdump カーネルの環境内から、クラッシュしたカーネルのメモリ領域を保存できることになります。
ローカルストレージのサイズが少ないシステムでは、カーネルダンプをネットワーク経由で採取したいこともあります。 Kdump では、 initrd
を介してネットワークインターフェイスの設定を行い、それを動作状態に移行させることができます。また、通常の LAN だけでなく VLAN にも対応しています。設定作業は YaST を使用して行うか、 /etc/sysconfig/kdump
ファイル内にある KDUMP_NETCONFIG
変数を設定してください。
Kdump を設定する際、採取したダンプイメージの保存先の場所を指定することができます (既定値: /var/crash
) 。この保存先は Kdump の設定時点でマウントしておかなければなりません。設定時点でマウントを行っていないと、設定が失敗します。
Kdump では設定を /etc/sysconfig/kdump
ファイルから読み込みます。お使いのシステムで Kdump を動作させるにあたって、事前の設定は特に必要ありません。 Kdump を既定の設定値のままで動作させたい場合は、下記の手順を実施してください:
18.4項 「crashkernel
割り当てサイズの計算」 の手順に従って、 Kdump で必要なメモリ量を決定します。決定後、 crashkernel
のカーネルパラメータを設定します。
コンピュータを再起動します。
Kdump サービスを有効化します:
#
systemctl
enable kdump
必要であれば /etc/sysconfig/kdump
ファイルを編集します。それぞれのオプションの意味について、詳しくはファイル内のコメント (英語) をお読みください。
sudo systemctl start kdump
を実行するか、システムを再起動して準備用のスクリプトを実行します。
既定値で Kdump の設定を行ったら、あとは期待通りに動作するかどうかを確認します。まずはお使いのシステム内に誰もログインしていないことと、システム内で重要なサービスを動作させていないことを確認して、下記の手順を実施します:
systemctl isolate rescue.target
と入力して実行し、レスキューモードのターゲットに切り替えます。
Kdump サービスを再起動します:
#
systemctl
start kdump
下記のコマンドを入力して実行し、ルートファイルシステム以外の全てのマウントを解除します:
#
umount
-a
ルートファイルシステムを読み込み専用モードで再マウントします:
#
mount
-o remount,ro /
procfs
インターフェイス内の Magic SysRq キー機能を利用して、 「カーネルパニック」 を動作させます:
#
echo
c > /proc/sysrq-trigger
KDUMP_KEEP_OLD_DUMPS
オプションは、カーネルダンプの保存数 (既定値: 5) を指定するためのものです。圧縮を行わない場合、ダンプのサイズは最大で物理メモリ (RAM) のサイズそのものになります。そのため、 /var
のパーティションに対しては、十分な空き領域を用意しておいてください。
情報採取用のカーネルが起動して、クラッシュしたほうのカーネルのメモリ状態をファイルシステムに保存します。保存先は KDUMP_SAVEDIR
オプションで設定します (既定値: /var/crash
) 。 KDUMP_IMMEDIATE_REBOOT
を yes
に設定していると、本番用のカーネルを利用してシステムを自動的に再起動します。再起動が終わったらログインを行い、 /var/crash
内にダンプファイルが作成されていることを確認してください。
YaST で Kdump を設定するには、まず yast2-kdump
パッケージをインストールする必要があります。インストール後は root
で 内の カテゴリにある を起動するか、もしくはコマンドラインで yast2 kdump
と入力して実行します。
まずは
ウインドウ内で を選択します。ウインドウを始めた開いたタイミングで、 18.4項 「crashkernel
割り当てサイズの計算」 の手順に従って判断を行い、値を入力してください。
コンピュータ内で Kdump を設定し、後からメモリ量や利用可能なハードディスクを変更した場合、 YaST では古い環境での値を表示し続けてしまいます。
この問題を回避するには、 18.4項 「crashkernel
割り当てサイズの計算」 で書かれている手順に従って必要なメモリ量を判断して、 YaST で設定をやり直してください。
左のペイン内で
を選択して、ダンプ内に含めるべきページを選択します。カーネルの問題をデバッグするだけであれば、これらのページは必要ではありません:ゼロ充填のページ
キャッシュページ
ユーザデータページ
フリーページ
ウインドウでは、ダンプの保存先の種類を選択したあと、保存先の場所を指定します。 FTP や SSH などのネットワークプロトコルを指定した場合は、必要なアクセス情報についても指定する必要があります。
Kdump のダンプの保存先と他のアプリケーションのダンプ保存先を同じパスに設定することもできます。この場合、古いダンプファイルの削除処理では、他のアプリケーションのダンプが除外され、削除は行われません。
Kdump に対して、そのイベントが発生した際に電子メールで通知を行いたい場合は、
のウインドウ内で設定を行います。また、必要であれば で必要な設定を行います。設定が完了したら を押すことで、設定が完了します。ダンプファイルには不用意に開示してはならない様々な機密情報が含まれています。このような機密情報を含むデータを信頼できないネットワーク経由で送信できるようにするため、 Kdump には、 SSH プロトコルを介してリモートのマシンにダンプファイルを送信できる機能が用意されています。
送信先のホストの識別情報は、あらかじめ Kdump 側で既知のものでなければなりません。これは、機密情報を含むデータを誤った (場合によっては悪意を持って偽装された) ホストに送信しないための仕組みです。 Kdump が新しい initrd
を生成する際、送信先のホストの識別情報を問い合わせるために ssh-keygen -F 宛先ホスト
を実行しますが、それは 宛先ホスト の公開鍵が既知である必要があるためです。公開鍵を既知のものにしておくための最も簡単な方法は、 root
で 宛先ホスト に接続してみることです。
また、 Kdump は送信先のホストとの間で認証できなければなりません。現時点では公開鍵認証にのみ対応しています。既定では Kdump は root
の機密鍵を使用して接続しようとしますが、通常は Kdump 用に個別の鍵を用意しておくことが望ましい設定です。個別の鍵は ssh-keygen
を利用して、下記のように実行することで作成することができます:
#
ssh-keygen
-f ~/.ssh/kdump_key
なお、パスフレーズの入力を求められた際には、何も入力せずに Enter を押してください (これでパスフレーズを使用せずに鍵を作成する意味になります) 。
あとは /etc/sysconfig/kdump
ファイルを開いて、 KDUMP_SSH_IDENTITY
の値を kdump_key に設定します。なお、 ~/.ssh
以外のディレクトリに配置している場合は、フルパスで指定してください。
次に、生成した Kdump の SSH 鍵を送信先のホストに送信して認証できるようにします。
#
ssh-copy-id
-i ~/.ssh/kdump_key TARGET_HOST
KDUMP_SAVEDIR
を設定します。これには 2 つの方法があります:
SFTP は SSH 経由でファイルを送信するための推奨される方法です。ただし、接続先のホストで SFTP サブシステムが有効化されていなければなりません (openSUSE Leap では既定で有効化されています) 。具体的には、下記のように指定します:
KDUMP_SAVEDIR=sftp://宛先ホスト/ダンプファイルの保存先パス
ディストリビューションによっては、接続先のホストで SSH 経由でコマンドを実行しなければならないものもあります。 openSUSE Leap では、この方法にも対応しています。この場合、接続先のホストでの Kdump のユーザには、ログインシェルが設定されていなければならず、 mkdir
, dd
, mv
の各コマンドを実行できなければなりません。具体的には下記のように指定します:
KDUMP_SAVEDIR=ssh://宛先ホストダンプファイルの保存先パス
新しい設定を適用するには、 Kdump のサービスを再起動してください。
ダンプファイルを保存することができたら、あとは解析するだけです。解析方法にはいくつかあります。
ダンプを解析する際に使用する最も基本的なツールは GDB です。このツールは最新の環境でも使用することができますが、いくつかの欠点や制限が存在しています:
GDB はカーネルのダンプを解析するための専用ツールではないこと。
GDB では 32 ビットプラットフォームで ELF64 バイナリ形式に対応していないこと。
GDB では ELF ダンプ以外の形式 (圧縮ダンプを含む) に対応していないこと。
上記のような理由から、 crash
ユーティリティが作成されました。このユーティリティはクラッシュダンプを解析するだけでなく、動作中のシステムもデバッグすることができます。また、 Linux カーネルのデバッグ専用の機能が用意され、高度なデバッグを行いたい場合に最適な仕組みです。
Linux カーネルをデバッグするには、まずデバッグ情報パッケージをもインストールしておく必要があります。お使いのシステムにインストールされているかどうかを確認するには、下記のコマンドを入力して実行します:
>
zypper
se kernel |grep
debug
openSUSE Leap 15.7 のシステムでオンライン更新を受け取るように設定している場合、 *-Debuginfo-Updates
という名前のオンラインリポジトリ内に 「debuginfo」 パッケージが存在しています。 YaST を利用するなどしてリポジトリを有効化してください。
ダンプを生成したマシンと同じマシンで crash
コマンドを実行し、採取したダンプを開きたい場合は、下記のようなコマンドを入力して実行します:
crash
/boot/vmlinux-6.4.0-150600.9-default.gz \
/var/crash/2024-04-23-11\:17/vmcore
ここで、最初のパラメータはカーネルイメージのパスを表しています。 2 つめのパラメータには、 Kdump で採取したダンプファイルを指定します。既定では、 /var/crash
ディレクトリ内に存在しています。
openSUSE Leap には kdumpid
と呼ばれるユーティリティ (同名のパッケージに含まれています) が存在し、これによって未知のカーネルダンプの情報を表示することができます。このユーティリティは、アーキテクチャやカーネルリリースなど、基本的な情報を抽出することができます。また、このユーティリティは lkcd, diskdump, Kdump, ELF ダンプの各形式に対応しているほか、 -v
オプションを付けて実行すると、マシンの種類やカーネルのバナー文字列、カーネルの設定フレーバーなども表示することができます。
Linux カーネルは Executable and Linkable Format (ELF) 形式で提供されます。このファイルは通常 vmlinux
と呼ばれ、コンパイル処理時に直接生成されます。ただし、特に AMD64/Intel 64 アーキテクチャで顕著ではありますが、全てのブートローダが ELF 形式に対応しているというわけではありません。 openSUSE® Leap で対応しているアーキテクチャごとに、下記のような仕組みになっています。
SUSE が提供する AMD64/Intel 64 向けのカーネルパッケージには、 vmlinuz
と vmlinux.gz
という 2 つのファイルが含まれています。
vmlinuz
: ブートローダから直接実行するほうのファイルです。
Linux カーネルは 2 種類のパーツから構成されています。 1 つはカーネルそれ自身 ( vmlinux
) 、もう 1 つはブートローダが実行するセットアップコードです。これら 2 つのパーツを 1 つにまとめて vmlinuz
というファイルに仕立て上げています (末尾が x
ではなく z
であることに注意してください) 。
カーネルのソースツリー内では、このファイルは bzImage
と呼ぶこともあります。
vmlinux.gz
: こちらは crash
や GDB が使用するファイルで、圧縮された ELF イメージの形態になっています。 ELF イメージは AMD64/Intel 64 のブートローダから使用されることがありませんので、圧縮されたファイルのみを提供しています。
POWER 上で動作する yaboot
ブートローダは ELF イメージの読み込みに対応していますが、圧縮されたファイルには対応していません。そのため、 POWER アーキテクチャ向けのカーネルパッケージには、 vmlinux
という ELF 形式の Linux カーネルファイルが含まれています。 crash
を動作させる前提で考えると、最も単純なアーキテクチャであると言えます。
なお、他のマシンでダンプを解析する場合は、コンピュータのアーキテクチャとデバッグに必要なファイルの両方を確認しなければならないことに注意してください。
他のコンピュータでダンプを解析する場合は、同じアーキテクチャの Linux マシンのみを使用することができます。アーキテクチャを確認したい場合は、 uname
-i
と入力して実行し、出力された内容を比較してください。
このほか、他のコンピュータでダンプを解析しようとしている場合は、 kernel
パッケージと kernel debug
パッケージが提供するファイルが必要となります。
まずはカーネルダンプと /boot
にあるカーネルイメージ、そしてそれに対応し、 /usr/lib/debug/boot
内にあるデバッグ情報ファイルを、 1 つのディレクトリ内にコピーしてまとめます。
また、 /lib/modules/$(uname -r)/kernel/
にあるカーネルモジュールと /usr/lib/debug/lib/modules/$(uname -r)/kernel/
にあるカーネルモジュール用のデバッグ情報ファイルを、 modules
サブディレクトリ内にコピーします。
ダンプファイルとカーネルイメージ、デバッグ情報ファイルを 1 つのディレクトリにまとめ、 modules
サブディレクトリ以下にカーネルモジュールとデバッグ情報ファイルを配置したら、あとは crash
ユーティリティを実行します:
>
crash
VMLINUX-バージョン vmcore
ダンプを解析しているコンピュータに関わらず、 crash ユーティリティは下記のような出力を生成するはずです:
>
crash
/boot/vmlinux-6.4.0-150600.9-default.gz \ /var/crash/2024-04-23-11\:17/vmcore crash 7.2.1 Copyright (C) 2002-2017 Red Hat, Inc. Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation Copyright (C) 1999-2006 Hewlett-Packard Co Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited Copyright (C) 2006, 2007 VA Linux Systems Japan K.K. Copyright (C) 2005, 2011 NEC Corporation Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc. Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Enter "help copying" to see the conditions. This program has absolutely no warranty. Enter "help warranty" for details. GNU gdb (GDB) 7.6 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu". KERNEL: /boot/vmlinux-6.4.0-150600.9-default.gz DEBUGINFO: /usr/lib/debug/boot/vmlinux-6.4.0-150600.9-default.debug DUMPFILE: /var/crash/2024-04-23-11:17/vmcore CPUS: 2 DATE: Thu Apr 23 13:17:01 2024 UPTIME: 00:10:41 LOAD AVERAGE: 0.01, 0.09, 0.09 TASKS: 42 NODENAME: eros RELEASE: 6.4.0-150600.9-default VERSION: #1 SMP 2024-03-31 14:50:44 +0200 MACHINE: x86_64 (2999 Mhz) MEMORY: 16 GB PANIC: "SysRq : Trigger a crashdump" PID: 9446 COMMAND: "bash" TASK: ffff88003a57c3c0 [THREAD_INFO: ffff880037168000] CPU: 1 STATE: TASK_RUNNING (SYSRQ)crash>
このコマンドは最初に、有益なデータを出力します。上記の例では、カーネルがクラッシュした時点で 42 個のタスクが動作していて、クラッシュの原因は PID 9446 のタスクから送信された SysRq トリガー、そしてそのプロセスは bash である (bash 内蔵コマンドである echo
コマンドでクラッシュを発生させたため) ことを示しています。
crash
ユーティリティは GDB を利用して動作する仕組みであるため、様々な追加コマンドも用意されています。たとえば bt
コマンドを何もパラメータを指定せずに実行すると、クラッシュが発生した時点での、そのタスクのバックトレースを表示することができます:
crash>
bt
PID: 9446 TASK: ffff88003a57c3c0 CPU: 1 COMMAND: "bash" #0 [ffff880037169db0] crash_kexec at ffffffff80268fd6 #1 [ffff880037169e80] __handle_sysrq at ffffffff803d50ed #2 [ffff880037169ec0] write_sysrq_trigger at ffffffff802f6fc5 #3 [ffff880037169ed0] proc_reg_write at ffffffff802f068b #4 [ffff880037169f10] vfs_write at ffffffff802b1aba #5 [ffff880037169f40] sys_write at ffffffff802b1c1f #6 [ffff880037169f80] system_call_fastpath at ffffffff8020bfbb RIP: 00007fa958991f60 RSP: 00007fff61330390 RFLAGS: 00010246 RAX: 0000000000000001 RBX: ffffffff8020bfbb RCX: 0000000000000001 RDX: 0000000000000002 RSI: 00007fa959284000 RDI: 0000000000000001 RBP: 0000000000000002 R8: 00007fa9592516f0 R9: 00007fa958c209c0 R10: 00007fa958c209c0 R11: 0000000000000246 R12: 00007fa958c1f780 R13: 00007fa959284000 R14: 0000000000000002 R15: 00000000595569d0 ORIG_RAX: 0000000000000001 CS: 0033 SS: 002bcrash>
これで何が起こったのかを知ることができます。 bash シェルの内蔵コマンドである echo
が、 /proc/sysrq-trigger
に文字を送信したために、クラッシュが発生していることになります。その文字に対応するハンドラが検出されると、 crash_kexec()
を実行しています。この関数は panic()
と呼ばれ、ここで Kdump がダンプを保存しています。
GDB の基本的なコマンドと bt
の拡張版に加えて、 crash ユーティリティには Linux カーネルの構造に関連したその他のコマンドも用意されています。これらのコマンドは Linux カーネルの内部データ構造を理解し、それを人間にとって読みやすい形式で表示します。たとえばクラッシュが発生した時点でのタスクの一覧は、 ps
で表示することができます。また sym
コマンドは、全てのカーネルシンボルの一覧とアドレスを表示したり、指定したシンボルに対して値を取得したりすることもできます。さらに files
コマンドでは、プロセスが開いている全てのファイルディスクリプタを表示することができます。 kmem
では、カーネルのメモリ使用率に関する詳細を表示することができます。 vm
では、個別のページマッピングのレベルに至るまで、プロセスの仮想メモリを調査することができます。分かりやすいコマンドの一覧は多く用意されているほか、様々なオプションを受け付けるようになっています。
上述のコマンドは、一般的な Linux コマンドである ps
や lsof
の機能に対応しているものです。なお、デバッガでイベントの正確な順序を確認したい場合は、 GDB の使用方法について知る必要があるほか、強固なデバッグスキルを必要とします。この種類の話題は本文書の範疇外にあたるものであるため、本書では説明していません。これに加えて、 Linux カーネルそのものの知識も必要となります。こちらについては、本文書の末尾にある参照情報をご確認ください。
Kdump の設定は /etc/sysconfig/kdump
内に保存されています。設定は YaST を利用しても行うことができます。 Kdump の設定オプションは、 内の › 内に存在しています。下記の Kdump オプションが用意されています。
カーネルダンプの保存先は、 KDUMP_SAVEDIR
オプションで指定します。ただし、カーネルダンプのサイズは大きくなることに注意してください。ディスクの空き容量から予想されるダンプファイルのサイズを引いた値が、 KDUMP_FREE_DISK_SIZE
よりも少ない場合、 Kdump はダンプの保存を行わなくなります。また、 KDUMP_SAVEDIR
では、 URL 形式にも対応しています。 URL 形式は プロトコル://仕様 の形式で指定し、 プロトコル は file
, ftp
, sftp
, nfs
, cifs
のいずれかを指定します。 仕様 はそれぞれのプロトコルに従った値を指定します。たとえばカーネルダンプを FTP サーバ内に保存したい場合は、 ftp://ユーザ名:パスワード@ftp.example.com:123/var/crash
のように指定します。
カーネルダンプは巨大なものであり、解析には必要のない多数のページをも含んでしまっています。 KDUMP_DUMPLEVEL
オプションを指定することで、これらの不要なページを省略することができます。設定可能な値は 0 から 31 までで、 0 を指定すると最も巨大なダンプファイルに、 31 を指定すると最も小さなダンプファイルになります。設定可能な値について、詳しくは kdump
のマニュアルページ ( man 7 kdump
) をお読みください。
場合によっては、カーネルダンプのサイズを小さくしておいたほうが都合のよい場合があります。たとえばネットワーク経由でダンプを転送するような場合や、ダンプディレクトリのディスク領域を節約したい場合などがそれにあたります。この場合は、 KDUMP_DUMPFORMAT
の値を compressed
に設定してください。なお、 crash
ユーティリティでは、圧縮されたダンプを動的に展開して使用することができます。
/etc/sysconfig/kdump
ファイルを変更した場合は、その変更点を反映させるため、必ず systemctl restart kdump.service
を実行する必要があります。実行しておかないと、次にシステムを再起動するまで、変更が反映されなくなってしまいます。
Kexec や Kdump の使用方法については、 1 箇所にまとまった情報源が存在していないのが現状です。下記にさまざまな側面で使用できる情報源 (いずれも英語のみ) を示します:
Kexec ユーティリティの使用方法については、 kexec
のマニュアルページ ( man 8 kexec
) をお読みください。
Kexec に関する一般的な情報については、 https://developer.ibm.com/technologies/linux/ をお読みください。
openSUSE Leap における Kdump の詳細については、 https://ftp.suse.com/pub/people/tiwai/kdump-training/kdump-training.pdf をお読みください。
Kdump の内部仕様に関する詳細については、 https://lse.sourceforge.net/kdump/documentation/ols2oo5-kdump-paper.pdf をお読みください。
crash
ダンプ解析ユーティリティやデバッグツールについての詳細は、それぞれ下記 (いずれも英語) をお読みください:
GDB の info ページ ( info gdb
) に加えて、印刷可能なガイド https://sourceware.org/gdb/documentation/ も提供されています。
crash ユーティリティには幅広い分野に対応したオンラインヘルプが用意されています。 help
コマンド のように入力すると、 コマンド に対するオンラインヘルプを表示することができます。
Perl の知識をお持ちであれば、 Alicia を利用してより簡単にデバッグを行うことができます。これは Perl ベースの crash ユーティリティ向けフロントエンドです。詳しくは https://alicia.sourceforge.net/ をお読みください。
Python をご利用になりたい場合は、 Pykdump をインストールして使用することをお勧めします。このパッケージは Python スクリプト経由で GDB を制御することができるものです。
Linux カーネルの内部情報に関する幅広い情報については、 Daniel P. Bovet 氏および Marco Cesati 氏による Understanding the Linux Kernel (ISBN 978-0-596-00565-8) をお読みください。