第20章 実行中のアプリケーションのデバッグ
本章では、開発者が直接アクセスできるマシンで、必要に応じて何度でも実行できるアプリケーションのデバッグ方法を紹介します。
20.1. デバッグ情報を使用したデバッグの有効化
アプリケーションおよびライブラリーをデバッグするには、デバッグ情報が必要です。以下のセクションでは、この情報を取得する方法を説明します。
20.1.1. デバッグの情報
実行可能なコードをデバッグする場合に、ツールやプログラマーは 2 種類の情報を使用して、バイナリーコードを理解することができます。
- ソースコードテキスト
- ソースコードテキストがバイナリーコードにどのように関連しているのかの説明
上記はデバッグ情報と呼ばれます。
Red Hat Enterprise Linux は、実行可能なバイナリー、共有ライブラリー、または debuginfo ファイルに ELF 形式を使用します。これらの ELF ファイル内では、DWARF 形式を使用してデバッグ情報が保持されます。
DWARF シンボルは、readelf -w file
コマンドを使用して読み込みます。
STABS は UNIX で使用される場合もあります。STABS は、機能が少ない旧式の形式です。Red Hat はこの使用を推奨していません。GCC および GDB では、STABS の実稼働および使用はベストエフォートでのみサポートされます。Valgrind および elfutils などの他のツールでは、STABS のサポートはありません。
関連資料
20.1.2. GCC を使用した C および C++ アプリケーションのデバッグの有効化
デバッグ情報のサイズが大きい場合、その情報はデフォルトで実行可能ファイルに含まれません。GCC を使用した C および C++ のアプリケーションのデバッグを有効にするには、コンパイラーに対して、デバッグ情報を作成するように、明示的に指示する必要があります。
GCC を使用したデバッグ情報の作成の有効化
コードのコンパイルおよびリンク時に GCC でデバッグ情報の作成を有効にするには、-g
オプションを使用します。
$ gcc ... -g ...
-
コンパイラーとリンカーで最適化を行うと、実行可能なコードを、元のソースコードと関連付けることが難しくなります。変数の最適化、ループのアンロール、周りの操作へのマージなどが行われる可能性があります。これにより、デバッグに負の影響が及ぶ可能性があります。デバッグの体験を向上するには、
-Og
オプションを指定して、最適化を設定することを考慮してください。ただし、最適化レベルを変更すると、実行可能なコードが変更され、バグを取り除くための実際の動作が変更される可能性があります。 -
-fcompare-debug
GCC オプションでは、GCC でコンパイルしたコードを、デバッグ情報を使用して (または、デバッグ情報を使用せずに) テストします。このテストでは、出力されたバイナリーファイルの 2 つが同一であれば合格します。このテストを行うことで、実行可能なコードがデバッグオプションによる影響は受けないようにするだけでなく、デバッグコードにバグが含まれないようにします。-fcompare-debug
オプションを使用するとコンパイルの時間が大幅に伸びることに留意してください。このオプションに関する詳細は、GCC の man ページを参照してください。
関連資料
- 「デバッグ情報を使用したデバッグの有効化」
- GNU コンパイラーコレクション (GCC) の使用: 「3.10 Options for Debugging Your Program」
- GDB でのデバッグ: 18.3 Debugging Information in Separate Files
GCC の man ページ:
$ man gcc
20.1.3. Debuginfo パッケージ
Debuginfo パッケージには、プログラムとライブラリーのデバッグ情報と、デバッグソースコードが含まれます。
前提条件
Debuginfo パッケージ
Red Hat Enterprise Linux リポジトリーのパッケージにインストールされているアプリケーションやライブラリーの場合は、別のチャンネルで提供されている別の debuginfo
パッケージとしてデバッグ情報とデバッグソースコードを取得することができます。debuginfo パッケージには .debug
ファイルが含まれており、その中には、バイナリーパッケージのコンパイルに使用する DWARF debuginfo とソースファイルがあります。debuginfo パッケージの内容は、/usr/lib/debug
ディレクトリーにインストールされます。
debuginfo パッケージでは、名前、バージョン、リリース、アーキテクチャーが同じバイナリーパッケージでのみ有効なデバッグ情報が提供されます。
-
バイナリーパッケージ:
packagename-version-release.architecture.rpm
-
Debuginfo パッケージ:
packagename-debuginfo-version-release.architecture.rpm
20.1.4. GDB を使用したアプリケーションまたはライブラリー向けの debuginfo パッケージの取得
GNU デバッガー (GDB) は、自動的に足りないデバッグ情報を認識して、パッケージ名を解決します。
前提条件
- デバッグするアプリケーションまたはライブラリーがシステムにインストールされていること
- システムに GDB がインストールされていること
-
システムに
debuginfo-install
ツールがインストールされていること
手順
デバッグするアプリケーションまたはライブラリーに割り当てられた GDB を起動します。GDB は不足しているデバッグ情報を自動的に認識し、実行するコマンドを提案します。
$ gdb -q /bin/ls Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done. (no debugging symbols found)...done. Missing separate debuginfos, use: debuginfo-install coreutils-8.22-21.el7.x86_64 (gdb)
これ以上先に進まずに GDB を終了します。 q を入力して、Enter を押します。
(gdb) q
GDB が提案するコマンドを実行して、必要な debuginfo パッケージをインストールします。
# debuginfo-install coreutils-8.22-21.el7.x86_64
アプリケーションまたはライブラリーの debuginfo パッケージをインストールすると、すべての依存関係の debuginfo パッケージもインストールされます。
-
GDB が debuginfo パッケージを提案できない場合には、 「手動でのアプリケーションまたはライブラリー向けの
debuginfo
パッケージの取得」の手順に従ってください。
関連資料
- 『Red Hat Developer Toolset User Guide』: 「Chapter 1.5, Installing Debugging Information」
- Red Hat ナレッジベースソリューション: 「RHEL システムで debuginfo パッケージをダウンロードまたはインストールする」
20.1.5. 手動でのアプリケーションまたはライブラリー向けの debuginfo
パッケージの取得
インストール用にどの debuginfo
パッケージをインストールするのかを手作業で選択するには、実行ファイルの場所を特定して、インストールするパッケージを検索します。
GDB を使用してインストール用のパッケージを決定すること を推奨します。この手動の手順は、GDB がインストールするパッケージを提案できない場合にのみ使用してください。
前提条件
- アプリケーションまたはライブラリーをシステムにインストールしている。
-
debuginfo
-install ツールをシステムで利用できるようにしておく。
手順
アプリケーションまたはライブラリーの実行可能ファイルを検索します。
which
コマンドを使用して、アプリケーションファイルを検索します。$ which nautilus /usr/bin/nautilus
locate
コマンドを使用して、ライブラリーファイルを検索します。$ locate libz | grep so /usr/lib64/libz.so /usr/lib64/libz.so.1 /usr/lib64/libz.so.1.2.7
デバッグの元の理由にエラーメッセージが含まれている場合、ライブラリーのファイル名に同じ追加の数字が含まれる結果を選択します。不明な点がある場合は、ライブラリーファイルの名前に追加の番号が含まれていないものを使用して、残りの手順を試してください。
注記locate
コマンドは mlocate パッケージで提供されます。このパッケージをインストールして、その使用を有効にするには、以下のコマンドを実行します。# yum install mlocate # updatedb
ファイルパスを使用して、対象のファイルを提供するパッケージを検索します。
# yum provides /usr/lib64/libz.so.1.2.7 Loaded plugins: product-id, search-disabled-repos, subscription-manager zlib-1.2.7-17.el7.x86_64 : The compression and decompression library Repo : @anaconda/7.4 Matched from: Filename : /usr/lib64/libz.so.1.2.7
この出力では、
name-version.distribution.platform
形式でパッケージの一覧が表示されます。yum
の出力で表示されるバージョンは実際にインストールされているバージョンでない場合があるので、この手順では、パッケージの name のみが重要です。重要この手順では結果が返されないので、どのパッケージがバイナリーファイル用のパッケージであるか、またこの手順が失敗したかどうかを判別することができません。
rpm
の低レベルのパッケージ管理ツールを使用して、どのパッケージバージョンがシステムにインストールされているかを確認します。パッケージ名を引数として使用します。$ rpm -q zlib zlib-1.2.7-17.el7.x86_64
この出力では、インストールされているパッケージの詳細が
name-version.distribution.platform
形式で表示されます。debuginfo-install
ユーティリティーを使用してdebuginfo
パッケージをインストールします。このコマンドで、直前の手順で確認したパッケージ名およびその他の詳細情報を使用します。# debuginfo-install zlib-1.2.7-17.el7.x86_64
アプリケーションまたはライブラリーの
debuginfo
パッケージをインストールすると、すべての依存関係のdebuginfo
パッケージもインストールされます。
関連資料
- 『Red Hat Developer Toolset User Guide』: 「Installing Debugging Information」
- ナレッジベースアーティクル: 「RHEL システムで debuginfo パッケージをダウンロードまたはインストールする」
20.2. GDB を使用したアプリケーションの内部状態の検証
アプリケーションが適切に機能しない理由を特定するには、その実行を制御し、デバッガーで内部状態を検査します。本セクションでは、このタスクに GNU デバッガー (GDB) を使用する方法を説明します。
20.2.1. GNU デバッガー (GDB)
デバッガーは、コード実行の制御や、コードの状態の検査を有効にするツールです。この機能は、プログラム内で何が発生しているのか、またその発生理由についての調査に使用します。
Red Hat Enterprise Linux には、コマンドラインユーザーインターフェースでこの機能を提供する GNU デバッガー (GDB) が含まれます。
GDB へのグラフィカルフロントエンドについては、Eclipse 統合開発環境をインストールします。「Using Eclipse」を参照してください。
GDB 機能
単一の GDB セッションで、以下をデバッグできます。
- マルチスレッドやフォーク用のプログラムをデバッグ
- 一度に複数のプログラムをデバッグ
-
TCP/IP ネットワーク接続経由で接続された
gdbserver
ユーティリティーを使用するリモートマシンまたはコンテナー内のプログラムをデバッグ
デバッグの要件
実行可能なコードをデバッグするには、GDB では適切なデバッグ情報が必要です。
- 独自に開発したプログラムの場合は、コードの構築時にデバッグ情報を作成できます。
- パッケージからインストールしたシステムプログラムの場合は、それぞれの debuginfo パッケージをインストールする必要があります。
20.2.2. プロセスへの GDB の割り当て
プロセスを検査するには、GDB がプロセスに 割り当てられている 必要があります。
前提条件
GDB でのプログラムの起動
プログラムがプロセスとして実行されていない場合は、GDB でプログラムを起動します。
$ gdb program
program は、ファイル名またはプログラムへのパスに置き換えます。
GDB はプログラムの実行を開始します。run
コマンドでプロセスの実行を開始する前に、ブレークポイントと gdb
環境を設定できます。
実行中のプロセスへの GDB の割り当て
プロセスとしてすでに実行中のプログラムに GDB を割り当てるには、以下を実行します。
ps
コマンドで、プロセス id (pid) を検索します。$ ps -C program -o pid h pid
program は、ファイル名またはプログラムへのパスに置き換えます。
このプロセスに GDB を割り当てます。
$ gdb -p pid
pid は、
ps
の出力にある実際のプロセス ID 番号に置き換えます。
実行中のプロセスに実行中の GDB を割り当てる手順
実行中のプロセスに実行中の GDB を割り当てるには、以下を実行します。
GDB コマンド
shell
を使用してps
コマンドを実行し、プログラムのプロセス ID (pid) を検索します。(gdb) shell ps -C program -o pid h pid
program は、ファイル名またはプログラムへのパスに置き換えます。
attach
コマンドを使用して、GDB をプログラムに割り当てます。(gdb) attach pid
pid は、
ps
の出力にある実際のプロセス ID の番号に置き換えます。
場合によっては、GDB がそれぞれの実行可能ファイルを検索できない可能性があります。file
コマンドを使用して、パスを指定します。
(gdb) file path/to/program
関連資料
- GDB を使用したデバッグ: 2.1 Invoking GDB
- GDB を使用したデバッグ: 4.7 Debugging an Already-running Process
20.2.3. GDB でのプログラムコードの活用
GDB デバッガーがプログラムに割り当てられたら、複数のコマンドを使用して、プログラムの実行を制御できます。
前提条件
- GDB がシステムにインストールされている
必要なデバッグ情報を利用できる状態にしている。
- プログラムはコンパイルされ、デバッグ情報で構築されている。
- 関連する debuginfo パッケージがインストールされている。
- GDB がデバッグするプログラムに割り当てられている
コードを活用するための GDB コマンド
r
(run)-
プログラムの実行を開始します。引数を指定して
run
を実行すると、プログラムが通常起動しているかのように、指定した引数が実行可能ファイルに渡されます。通常、ユーザーはブレークポイントの設定後にこのコマンドを実行します。 start
-
プログラムの実行を開始してメイン機能の開始時に停止します。引数を指定して
start
を実行すると、プログラムが通常起動しているかのように、指定した引数が実行可能ファイルに渡されます。
c
(continue)現在の状態からプログラムの実行を継続します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムがシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
n
(next)現在のソースファイルでコードが次の行に到達するまで、現在の状態からプログラムの実行を続行します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムがシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
s
(step)-
step
コマンドは、現在のソースファイル内のコードの連続行ごとに実行を停止させます。ただし、実行が 関数呼び出し を含むソース行で停止中の場合には、GDB は、関数呼び出しを入力した後 (実行後ではなく)、実行を停止します。 until
location- location オプションで指定したコードの場所に到達するまで、実行が継続されます。
fini
(finish)プログラムの実行を再開し、実行が関数から戻り値として返された時点で停止します。プログラムの実行は、以下のいずれかが True になるまで継続します。
- ブレークポイントに到達した場合
- 指定の条件を満たした場合
- プログラムがシグナルを受信する場合
- エラーが発生した場合
- プログラムが終了する場合
q
(quit)- 実行を中断して、GDB を終了します。
関連資料
- 「定義したコードの場所で実行を停止するための GDB ブレークポイントの使用」
- GDB を使用したデバッグ - 4.2 Starting your Program
- GDB を使用したデバッグ - 5.2 Continuing and Stepping
20.2.4. GDB でのプログラム内部値の表示
プログラムの内部変数の値を表示することは、プログラムの実行内容を理解する際に重要です。GDB は、内部変数の検査に使用できる複数のコマンドを提供します。このセクションでは、これらのコマンドの中で最も有用なものを説明します。
前提条件
- GDB デバッガーを理解していること
プログラムの内部の状態を表示するための GDB コマンド
p
(print)指定された引数の値を表示します。引数には通常、単純な値 1 つや構造など、複雑度の異なる変数名を指定できます。引数には、プログラム変数やライブラリー関数の使用、テストするプログラムに定義する関数など、現在の言語で有効な式も指定できます。
pretty-printer Python スクリプトまたは Guile スクリプトを使用して GDB を拡張し、
print
コマンドを使用して、(クラス、構造などの) データ構造をカスタマイズ表示することができます。bt
(backtrace)現在の実行ポイントに到達するために使用される関数呼び出しのチェーン、または実行が終了するまで使用される関数のチェーンを表示します。これは、原因を特定しにくい、深刻なバグ (セグメント障害など) を調査する場合に便利です。
backtrace
コマンドにfull
オプションを追加すると、ローカル変数も表示されます。frame filter Python スクリプトを使用して GDB を拡張し、
bt
とinfo frame
コマンドでデータをカスタマイズして表示できます。フレーム という用語は、1 つの関数呼び出しに関連付けられたデータを指します。info
info
コマンドは、さまざまな項目に関する情報を提供する汎用コマンドです。このコマンドでは、項目をオプションとして指定できます。-
info args
コマンドは、現在選択されているフレームの関数呼び出しのオプションを表示します。 -
info locals
コマンドは、現在選択されているフレームにローカル変数を表示します。
使用できる項目を一覧表示するには、GDB セッションで
help info
コマンドを実行します。(gdb) help info
-
l
(list)-
プログラムが停止するソースコードの行を表示します。このコマンドは、プログラムの実行が停止した場合のみ利用できます。
list
は、厳密には内部状態を表示するコマンドではありませんが、ユーザーがプログラムの実行の次の手順で内部状態にどのような変更が発生するかを理解するのに役立ちます。
関連資料
- Red Hat Developer ブログエントリー: The GDB Python API
- GDB でのデバッグ: 10.9 Pretty Printing
20.2.5. 定義したコードの場所で実行を停止するための GDB ブレークポイントの使用
多くの場合、特定のコードの行に到達するまでプログラムを実行させることには利点があります。
前提条件
- GDB を理解していること
GDB でのブレークポイントの使用
ブレークポイントは、プログラムの実行を停止するように GDB に指示を出すマーカーです。ブレークポイントは一般的に、ソースコードの行と関連付けられており、ブレークポイントを配置するには、ソースファイルと行数を指定する必要があります。
ブレークポイントを配置する には、以下を行います。
ソースコード ファイル の名前と、そのファイルの 行 を指定します。
(gdb) br file:line
ファイル が存在しない場合は、現在の実行ポイントにソースファイルの名前が使用されます。
(gdb) br line
または、関数名を使用して、起動時にブレークポイントを配置します。
(gdb) br function_name
タスクを特定の回数反復すると、プログラムでエラーが発生する可能性があります。実行を停止するために追加の 条件 を指定するには、以下を実行します。
(gdb) br file:line if condition
condition を、C または C++ 言語の条件に置き換えます。file と line は、上記と同様に、ファイル名および行数に置き換えます。
全ブレークポイントおよびウォッチポイントの状態を 検査 する場合は、以下のコマンドを実行します。
(gdb) info br
info br
の出力で表示された 番号 を使用してブレークポイントを 削除 するには、以下のコマンドを実行します。(gdb) delete number
指定の場所のブレークポイントを 削除 するには、以下を実行します。
(gdb) clear file:line
関連資料
- GDB でのデバッグ: 5.1 Breakpoints, Watchpoints, and Catchpoints
20.2.6. データへのアクセスや変更時に実行を停止するための GDB ウォッチポイントの使用
多くの場合、特定のデータが変更されたり、アクセスされるまでプログラムを実行させることには利点があります。このセクションでは、最も一般的ウォッチポイントを取り上げます。
前提条件
- GDB を理解していること
GDB でのウォッチポイントの使用
ウォッチポイントは、プログラムの実行を停止するように GDB に指示を出すマーカーです。ウォッチポイントはデータに関連付けられます。ウォッチポイントを配置するには、変数、複数の変数、またはメモリーアドレスを指定する必要があります。
データの 変更 (書き込み) を行うために、ウォッチポイントを 配置 するには、以下を実行します。
(gdb) watch expression
expression を、監視する内容を記述する式に置き換えます。変数の場合、式 は、変数の名前と同じです。
データ アクセス (読み込み) のためのウォッチポイントを 配置 するには、以下を実行します。
(gdb) rwatch expression
任意の データへのアクセス (読み取りおよび書き込みの両方) のためにウォッチポイントを 配置 するには、以下を実行します。
(gdb) awatch expression
全ウォッチポイントおよびブレークポイントの状態を 検査 するには以下を実行します。
(gdb) info br
ウォッチポイントを 削除 するには、以下を実行します。
(gdb) delete num
num オプションを、
info br
コマンドで報告される番号に置き換えます。
関連資料
- GDB でのデバッグ: 5.1.2 Setting Watchpoints
20.2.7. GDB でのフォーク用またはスレッド化されたプログラムのデバッグ
プログラムによっては、フォークまたはスレッドを使用して、コードの並行実行を実行します。複数の同時実行パスをデバッグするには、特別な留意点があります。
前提条件
- GDB デバッガーを理解していること
- フォークおよびスレッドプロセスのコンセプトを理解していること
GDB でのフォークされたプログラムのデバッグ
フォークとは、プログラム (親) により、独立したコピー (子) を作成する状況のことを指します。以下の設定およびコマンドを使用して、実行するフォークに対する GDB の対応を変更します。
follow-fork-mode
設定で、フォークの後に GDB が親または子に従うかどうかを制御します。set follow-fork-mode parent
- フォークの後に、親プロセスのデバッグを行います。これはデフォルトです。
set follow-fork-mode child
- フォークの後に、子プロセスのデバッグを行います。
show follow-fork-mode
-
follow-fork-mode
の現在の設定を表示します。
set detach-on-fork
設定では、GDB が (フォローしていない) 他のプロセスを制御するか、そのまま実行させるかを制御します。set detach-on-fork on
-
フォローしていないプロセス (
follow-fork-mode
の値による) は切り離され、別個で実行されます。これはデフォルトです。 set detach-on-fork off
-
GDB は両方のプロセスの制御を維持します。フォローしているプロセス (
follow-fork-mode
の値による) は通常通りにデバッグされ、他は一時停止されます。 show detach-on-fork
-
現在の
detach-on-fork
設定を表示します。
GDB でのスレッド化されたプログラムのデバッグ
GDB には、個別のスレッドをデバッグして、独立して操作し、検査する機能があります。GDB が検証したスレッドのみを停止させるには、set non-stop on
コマンドおよび set target-async on
を使用します。上記のコマンドは、.gdbinit
ファイルに追加できます。その機能が有効になると、GDB がスレッドのデバッグを実行する準備が整います。
GDB は current thread の概念を使用します。デフォルトでは、コマンドは現在のスレッドのみに適用されます。
info threads
-
現在のスレッドを示す
id
番号およびgid
番号を使用してスレッドの一覧を表示します。 thread id
-
指定した
id
を現在のスレッドとして設定します。 thread apply ids command
-
command
コマンドをids
で表示した全スレッドに適用します。ids
オプションは、スペースで区切られたスレッド ID の一覧です。当別な値all
で、全スレッドにコマンドを適用します。 break location thread id if condition
-
特定の
location
、特定のcondition
に、スレッド番号id
に対してのみ、ブレークポイントを設定します。 watch expression thread id
-
スレッド番号
id
に対してのみ、expression
で定義されるウォッチポイントを設定します。 command&
-
command
コマンドを実行すると、GDB プロンプト ((gdb)
) に即座に戻り、バックグラウンドでコードの実行が続行されます。 interrupt
- バックグラウンドでの実行が停止されます。
関連資料
- GDB を使用したデバッグ: 4.10 Debugging Programs with Multiple Threads
- GDB を使用したデバッグ: 4.11 Debugging Forks
20.3. アプリケーションの対話の記録
アプリケーションの実行可能コードは、オペレーティングシステムや共有ライブラリーのコードと対話します。これらの対話に関するアクティビティーログを記録すると、実際のアプリケーションコードをデバッグせずに、アプリケーションの動作を詳細にわたり知ることができます。また、アプリケーションの対話を分析すると、バグが発生した状況をピンポイントで特定しやすくなります。
20.3.1. アプリケーションの対話の記録に役立つツール
Red Hat Enterprise Linux は、アプリケーションの相互作用を分析するための複数のツールを提供しています。
- strace
strace
ツールは、システムコール、シグナル配信、プロセス状態の変更など、アプリケーションと Linux カーネル間の対話 (および改ざん) のトレースを有効にします。-
strace
は、パラメーターを解釈し、結果として下層にあるカーネルコードに関する知識が得られるため、strace
の出力が詳細にわたり、呼び出しについて詳しく説明します。数値は、定数名、フラグリストに展開されたビット単位の結合フラグ、実際の文字列を提供するために逆参照された文字配列へのポインターなどにそれぞれ変換されます。最新のカーネル機能のサポートがない場合があります。 - [command]`strace を使用するために、ログフィルターの設定以外に、特別な設定は必要ありません。
- strace でアプリケーションコードを追跡すると、アプリケーションの実行速度が大幅に遅くなるため、strace は、多くの実稼働環境のデプロイメントには適しません。代わりに、このような場合に SystemTap の使用を検討してください。
- 追跡されたシステムコールとシグナルの一覧をフィルタリングして、キャプチャーしたデータ量を減らすことができます。
- strace は kernel-userspace の対話のみをキャプチャーし、ライブラリーコールなどはを追跡しません。ライブラリー呼び出しの追跡には ltrace の使用を検討してください。
-
- ltrace
ltrace
ツールを使用すると、アプリケーションのユーザー空間呼び出しのログを共有オブジェクト (動的ライブラリー) に記録できます。-
ltrace
は、ライブラリーへの呼び出しを追跡できるようにします。 - トレースされた呼び出しをフィルタリングして、取得するデータ量を減らすことができます。
-
ltrace
を使用するために、ログフィルターの設定以外に、特別な設定は必要ありません。 -
ltrace
は、軽量、高速で、strace
の代わりとして使用できます。strace
でカーネル関数を追跡する代わりに、ltrace
でglibc
などのライブラリー内の各インターフェースを追跡できます。ただし、システムコールのトレースでltrace
は strace より正確性に欠ける点に注意してください。 -
ltrace
はstrace
などの既知の呼び出しを処理しないので、ライブラリーの関数に渡す値の情報は提供されません。ltrace
出力には、ライブラリー用にバンドルされたライブラリー関数の引数メタデータと、生の数値とポインターのみが含まれます。ltrace
の出力を解釈するには、出力に含まれるライブラリーの実際のインターフェース宣言を確認する必要があります。
-
- SystemTap
SystemTap は、Linux システム上で実行中のプロセスおよびカーネルアクティビティーを調査するための有用なインストルメンテーションプラットフォームです。SystemTap は、独自のスクリプト言語を使用してカスタムイベントハンドラーをプログラミングします。
-
strace
とltrace
の使用と比較して、ロギングのスクリプトを作成すると、初期の設定フェーズでより多くの作業が必要になります。ただし、スクリプト機能は単にログを生成するだけでなく、SystemTap の有用性を高めます。 - SystemTap は、カーネルモジュールを作成し、挿入すると機能します。SystemTap は効率的に使用でき、システムまたはアプリケーションの実行速度が大幅に低下することはありません。
- SystemTap には一連の使用例が提供されます。
-
- GDB
GNU デバッガーは主に、ロギングではなく、デバッグを目的としています。ただし、その機能の一部は、アプリケーションの対話が主要なアクティビティーとなるシナリオでも役に立ちます。
- GDB では、対話イベントを取得して、後に続く実行パスを即時にデバッグするように、都合よく組み合わせることができます。
- GDB は、他のツールで問題のある状況を最初に特定した後、頻度の低いイベントや特異なイベントへの応答を分析するのに最適です。イベントが頻繁に発生するシナリオで GDB を使用すると、効率が悪くなったり、不可能になったりします。
関連資料
20.3.2. strace でのアプリケーションのシステム呼び出しの監視
strace
ツールは、アプリケーションを実行するシステム (カーネル) 呼び出しの監視を有効にします。
前提条件
手順
- 監視するシステム呼び出しを特定します。
監視するプログラムが実行していない場合は、
strace
を起動して、プログラム を指定します。$ strace -fvttTyy -s 256 -e trace=call program
call を、表示するシステム呼び出しに置き換えます。
-e trace=call
オプションは複数回使用できます。何も指定しない場合には、strace
はすべてのシステム呼び出しタイプを表示します。詳しい情報は、strace(1) の man ページを参照してください。プログラムがすでに実行中の場合は、プロセス id (pid) を検索して、その id に
strace
を割り当てます。$ ps -C program (...) $ strace -fvttTyy -s 256 -e trace=call -ppid
フォークしたプロセスまたはスレッドを追跡しない場合には、
-f
オプションは指定しないでください。strace
は、アプリケーションで作成したシステム呼び出しとその詳細を表示します。ほとんどの場合、システム呼び出しのフィルターが設定されていないと、アプリケーションとそのライブラリーは多数の呼び出しを行い、
strace
出力がすぐに表示されます。strace
は、プログラムが終了すると終了します。追跡しているプログラムの終了前に監視を中断するには、
を押します。-
strace
でプログラムを起動した場合には、プログラムはstrace
と共に終了します。 -
実行中のプログラムに
strace
を割り当てた場合には、プログラムはstrace
と共に終了します。
-
アプリケーションが実行したシステム呼び出しの一覧を分析します。
- リソースへのアクセスや可用性の問題は、エラーを返す呼び出しとしてログに表示されます。
- システム呼び出しや呼び出しシーケンスのパターンに渡す値により、アプリケーションの動作の原因が分かります。
- アプリケーションがクラッシュした場合に、重要な情報はおそらく、ログの最後に表示されます。
- 出力には多くの追加情報が含まれています。ただし、より正確なフィルターを作成して、手順を繰り返すことができます。
出力を確認することにも、ファイルに保存することにも利点があります。これを実行するには、tee
コマンドを使用します。
$ strace ... |& tee your_log_file.log
関連資料
- strace(1) man ページ
- ナレッジベースアーティクル: 「strace を使用して、コマンドが実行したシステムコールを追跡する」
- 『Red Hat Developer Toolset User Guide』: strace
20.3.3. ltrace でのアプリケーションのライブラリー関数呼び出しの監視
ltrace
ツールは、ライブラリー (共有オブジェクト) で利用可能な関数に対するアプリケーションの呼び出しを監視できます。
前提条件
手順
- 可能であれば、対象のライブラリーおよび関数を特定します。
監視するプログラムが実行されていない場合には、
ltrace
を起動して、プログラム を指定します。$ ltrace -f -l library -e function program
-e
と-l
のオプションを使用して出力をフィルタリングします。-
function として表示される関数の名前を指定します。
-e function
オプションは複数回使用できます。何も指定しない場合は、ltrace
はすべての関数への呼び出しを表示します。 -
関数を指定するのではなく、
-l library
オプションでライブラリー全体を指定できます。このオプションは、-e function
オプションと同様に動作し ます。
詳細情報は、man ページの ltrace(1) を参照してください。
プログラムがすでに実行中の場合は、プロセス id (pid) を検索して、その id に
ltrace
を割り当てます。$ ps -C program (...) $ ltrace ... -ppid
フォークしたプロセスまたはスレッドを追跡しない場合には、
-f
オプションは指定しないでください。-
function として表示される関数の名前を指定します。
ltrace
はアプリケーションのライブラリー呼び出しを表示します。多くの場合、アプリケーションは大量の呼び出しを作成し、フィルターが設定されていない場合には、
ltrace
の出力がすぐに表示されます。ltrace
は、プログラムが終了すると終了します。追跡しているプログラムの終了前に監視を中断するには、
を押します。-
ltrace
でプログラムを起動した場合には、プログラムはltrace
と共に中断します。 -
実行中のプログラムに
ltrace
を割り当てると、プログラムはltrace
と共に終了します。
-
アプリケーションが実行したライブラリー呼び出しの一覧を分析します。
- アプリケーションがクラッシュした場合に、重要な情報はおそらく、ログの最後に表示されます。
- 出力には不要な情報が多く含まれています。ただし、より正確なフィルターを作成して、手順を繰り返すことができます。
出力を確認することにも、ファイルに保存することにも利点があります。これを実行するには、tee
コマンドを使用します。
$ ltrace ... |& tee your_log_file.log
関連資料
- strace(1) man ページ
- 『Red Hat Developer Toolset User Guide』: ltrace
20.3.4. SystemTap でのアプリケーションのシステム呼び出しの監視
SystemTap ツールを使用すると、カーネルイベントにカスタムイベントハンドラーを登録できます。strace
と比較すると、これは使いにくくなりますが、効率性は高く、より複雑な処理ロジックを使用することができます。
前提条件
手順
以下の内容で
my_script.stp
ファイルを作成します。probe begin { printf("waiting for syscalls of process %d \n", target()) } probe syscall.* { if (pid() == target()) printf("%s(%s)\n", name, argstr) } probe process.end { if (pid() == target()) exit() }
監視するプロセスのプロセス ID (pid) を検索します。
$ ps -aux
スクリプトで SystemTap を実行します。
# stap my_script.stp -x pid
pid の値は、プロセス ID です。
スクリプトはカーネルモジュールにコンパイルされ、それが読み込まれます。これにより、コマンドの入力から出力の取得までにわずかな遅延が生じます。
- プロセスでシステム呼び出しが実行されると、呼び出し名とパラメーターがターミナルに出力されます。
-
プロセスが終了した場合、または
Ctrl+C
を押すと、スクリプトは終了します。
関連資料
- 『SystemTap ビギナーズガイド』
- SystemTap タップセットリファレンス
-
strace
機能関連の SystemTap スクリプト (/usr/share/systemtap/examples/process/strace.stp
)
20.3.5. GDB を使用したアプリケーションシステム呼び出しの遮断
GDB は、プログラムの実行中に発生するさまざまな状況において実行を停止することができます。プログラムがシステム呼び出しを実行する際に実行を停止するには、GDB catchpoint を使用します。
前提条件
GDB の使用によるシステム呼び出しでのプログラム実行の停止
キャッチポイントを設定します。
(gdb) catch syscall syscall-name
catch syscall
コマンドは、プログラムがシステム呼び出しが行われた時に実行を停止する特別なタイプのブレークポイントを設定します。syscall-name
オプションは、呼び出しの名前を指定します。様々なシステム呼び出しに対して複数のキャッチポイントを指定することができます。syscall-name
オプションに何も指定しない場合には、システム呼び出しがあると GDB が停止してしまいます。プログラムが実行を開始していない場合は、これを開始します。
(gdb) r
プログラムの実行が一時停止しているだけの場合は、これを再開します。
(gdb) c
- GDB は、指定のシステム呼び出しがプログラムによって実行された後に実行を一時停止します。
関連資料
20.3.6. アプリケーションによるシグナル処理を遮断するための GDB の使用
GDB は、プログラムの実行中に発生するさまざまな状況において実行を停止することができます。プログラムがオペレーティングシステムからシグナルを受信した時に実行を停止するには、GDB の キャッチポイント を使用します。
前提条件
GDB でのシグナル受信時のプログラム実行の停止
キャッチポイントを設定します。
(gdb) catch signal signal-type
catch signal
コマンドは、プログラムがシステム呼び出しを受信する際に実行を停止する特殊なタイプのブレークポイントを設定します。signal-type
オプションは、シグナルのタイプを指定します。すべてのシグナルを取得するには、特別な値'all'
を使用します。プログラムが実行を開始していない場合は、これを開始します。
(gdb) r
プログラムの実行が一時停止しているだけの場合は、これを再開します。
(gdb) c
- GDB は、プログラムが指定のシグナルを受けると実行を停止します。
関連資料
このページには機械翻訳が使用されている場合があります (詳細はこちら)。