Linuxの深層を探るstrace入門:システムコール追跡と障害解析

はじめに

Linux環境における障害調査やパフォーマンス分析において、ユーザー空間のアプリケーションがカーネルとどのように通信しているかを把握することは極めて重要です。本記事では、低レベルなシステムコールをリアルタイムに傍受・可視化できる強力な診断ユーティリティ strace を導入し、その仕組みと実践的なトラブルシューティング手法を解説します。

straceのセットアップと基本的なシステムコール追跡

検証を始める準備として、パッケージインデックスを更新したうえで strace をシステムにインストールします。

apt-get update -qq && apt-get install -y strace

トレース対象として利用するシンプルなテキストデータを /tmp/testfile.txt に書き出します。

echo ‘Linux strace test content’ > /tmp/testfile.txt

strace は、プロセスが動作中に発行するシステムコールや受信シグナルをフックし、標準エラー出力に展開するツールです。
例えば cat コマンドの実行を strace 経由で監視すると、ファイルをディスクリプタとして開く openat、内容をメモリへ読み込む read、端末画面へ出力する write、そしてディスクリプタを破棄する close という一連のカーネル通信の全容が明らかになります。
⚙️ [主要オプション一覧]

-c : 各システムコールの総呼び出し回数、累積実行時間、失敗エラー件数などを集計したサマリーレポートを出力します。
-e : 追跡対象としたい特定のシステムコール名やイベント分類のみを抽出して表示します。
-o : コンソールに流れるトレース出力を画面ではなく指定したログファイルへリダイレクトして記録します。
-p : 既に稼働中のプロセスID(PID)を指定して動的にトレースをアタッチします。
-T : 各システムコールの処理に費やされた所要時間をマイクロ秒単位で行末に表示します。
-tt : コールが発生した厳密なタイムスタンプ(時:分:秒.マイクロ秒)を各行の先頭に付与します。
-s : 引数として渡された文字列パラメータの最大表示サイズ(バイト単位)を制御します。

strace cat /tmp/testfile.txt

特定システムコールのフィルタリング(-e trace オプション)

膨大なトレースログから必要な情報のみを抽出したい場合は、-e trace= によるフィルタリングが有効です。
strace -e trace=openat,read,write,close cat /tmp/testfile.txt を実行すると、起動時に発生する無数の環境初期化処理をスキップし、指定した4つのファイルI/O関連コールのみを絞り込んで追跡できます。
カンマ区切りで対象コールを定義することで、ノイズを排除し本質的な処理フローに集中できます。

strace -e trace=openat,read,write,close cat /tmp/testfile.txt

個々のシステムコール名を1つずつ指定する代わりに、事前定義されたトレースクラスを活用することも可能です。
strace -e trace=file ls -l /tmp/testfile.txt では、file クラスを指定することにより、パス探索、アクセス権検証、ファイルステータス取得など、ファイル操作全般に関連するコール群を一括でトラッキングできます。

strace -e trace=file ls -l /tmp/testfile.txt

システムコール統計の集計とボトルネック検出(-c オプション)

プロセスの負荷傾向をプロファイリングする際には、集計モードである -c が絶大な威力を発揮します。
strace -c ls -la /usr/bin > /dev/null コマンドは、膨大な数のバイナリが存在するディレクトリを探索する際に消費された全システムコールの統計サマリーを生成します。
標準出力を /dev/null に捨てて描画オーバーヘッドを省くことで、処理完了時に各コールの時間占有率、平均処理時間、実行回数、エラー発生率を整理された一覧表として確認できます。

strace -c ls -la /usr/bin > /dev/null

文字列検索タスクに対しても同様のアプローチで内部コストを検証できます。
strace -c grep -rn 'root' /etc/passwd > /dev/null を実行すると、検索処理の中でどのシステムコール(ファイルオープンやリード処理など)に最も時間を要しているかが数値化され、パフォーマンスネックの正確な所在を即座に割り出すことが可能です。

strace -c grep -rn ‘root’ /etc/passwd > /dev/null

稼働中プロセスの追跡とファイルへのログ退避(-p, -o オプション)

本番環境で既に稼働しているサービスやデーモンのトラブルシュートを想定し、バックグラウンドタスク sleep 100 & を生成して検証します。

sleep 100 &

直前にバックグラウンド投入されたプロセスの識別子をシェルの特殊パラメータから取得し、変数へ格納します。

TARGET_PID=$!

strace -p $TARGET_PID -o /tmp/strace_output.log -t & コマンドにより、稼働中プロセスのPIDへアタッチしてシステムコール追跡をバックグラウンドで開始し、秒刻みの時刻情報付きログを /tmp/strace_output.log に保存します。
現在のシェルセッションを占有することなくログをバックグラウンド退避できるため、稼働中デーモンの異常動作を安全に保全・監査できます。

strace -p $TARGET_PID -o /tmp/strace_output.log -t &

strace が対象プロセスのトレースを確実に確立するまでの待機時間として sleep 1 を挟みます。

sleep 1

トレース対象プロセスへ終了シグナルを送るため、kill $TARGET_PID を実行します。

kill $TARGET_PID

出力ログの先頭部分を head -n 20 /tmp/strace_output.log でプレビューします。
採取されたログから、対象プロセスが SIGTERM を受信し、終了処理を経て安全にシャットダウンされるまでのシステムコールの遷移が明瞭に記録されていることが確認できます。

head -n 20 /tmp/strace_output.log

本稿では、Linuxプロセスの内面を透過的に観察できる strace の基本操作と実践的な活用パターンを紹介しました。
原因の特定が難しいハングアップやファイルアクセスの不具合に直面した際には、カーネルレイヤーの真実を語るシステムコールを直接トレースし、精度の高いトラブルシューティングを実現してください。