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 で情報採取用のカーネルを起動する 場合、このカーネル用のメモリ領域を割り当てておく必要があります。割り当てるべきサイズはコンピュータのハードウエア設定によって異なりますので、あらかじめ指定しておく必要があります。
割り当てるべきサイズは、お使いのコンピュータのハードウエアアーキテクチャによっても異なります。それぞれ下記の手順をお読みのうえ、必要なサイズを判断してください。
コンピュータに対する基礎値を得るには、端末内で下記のコマンドを入力し実行します:
#kdumptoolcalibrate 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 ツールを利用することで、現時点で有効化されているデバイスや使用しているデバイスを除き、それ以外の全てのデバイスを無視する設定を生成することができます。
>sudocio_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 のサービスをシステムの起動時に開始するようにするには、下記のように入力して実行します:
>sudosystemctl enable kexec-load.service
Kexec サービスを開始するには、下記のように入力して実行します:
>sudosystemctl 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 サービスを有効化します:
>sudosystemctlenable kdump
必要であれば /etc/sysconfig/kdump ファイルを編集します。それぞれのオプションの意味について、詳しくはファイル内のコメント (英語) をお読みください。
初期化スクリプトを一度だけ動作させます。
>sudosystemctlstart kdump
システムを再起動します。
既定値で Kdump の設定を行ったら、あとは期待通りに動作するかどうかを確認します。まずはお使いのシステム内に誰もログインしていないことと、システム内で重要なサービスを動作させていないことを確認して、下記の手順を実施します:
rescue ターゲットに切り替えます。
>sudosystemctlisolate rescue.target
Kdump サービスを再起動します:
>sudosystemctlstart kdump
下記のコマンドを入力して実行し、ルートファイルシステム以外の全てのマウントを解除します:
>sudoumount-a
ルートファイルシステムを読み込み専用モードで再マウントします:
>sudomount-o remount,ro /
procfs インターフェイス内の Magic SysRq キー機能を利用して、 「カーネルパニック」 を動作させます:
>sudoechoc > /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 カーネルをデバッグするには、まずデバッグ情報パッケージをもインストールしておく必要があります。お使いのシステムにインストールされているかどうかを確認するには、下記のコマンドを入力して実行します:
>zypperse kernel |grepdebug
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 ユーティリティを実行します:
>crashVMLINUX-バージョン 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>btPID: 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) をお読みください。