strace コマンド

プロセスのシステムコールとシグナルをトレースします。

概要

strace は Linux 用の診断およびデバッグユーティリティで、指定されたプログラムのシステムコールとシグナルをトレースします。プロセスによって行われるシステムコールと受信したシグナルを傍受して記録するため、トラブルシューティング、プログラムの動作の理解、アプリケーションの問題の診断に非常に役立つツールです。

オプション

-f

現在トレースされているプロセスによって作成される子プロセスをトレースします。

$ strace -f ./my_program
execve("./my_program", ["./my_program"], 0x7ffc8e5bb4a0 /* 58 vars */) = 0
brk(NULL)                               = 0x55a8a9899000
[pid 12345] clone(child_stack=NULL, flags=CLONE_CHILD|SIGCHLD, ...) = 12346
[pid 12346] execve("/bin/ls", ["ls"], 0x7ffc8e5bb4a0 /* 58 vars */) = 0

-p PID

指定された PID のプロセスにアタッチしてトレースを開始します。

$ strace -p 1234
strace: Process 1234 attached
read(3, "Hello, world!\n", 4096)        = 14
write(1, "Hello, world!\n", 14)         = 14

-o FILENAME

トレース出力を stderr ではなくファイルに書き込みます。

$ strace -o trace.log ls
$ cat trace.log
execve("/bin/ls", ["ls"], 0x7ffc8e5bb4a0 /* 58 vars */) = 0
brk(NULL)                               = 0x55a8a9899000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)

-e EXPR

トレースするイベントやトレース方法を修正する修飾式です。

$ strace -e open,close ls
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
close(3)                                = 0
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
close(3)                                = 0

-c

各システムコールの時間、呼び出し回数、エラーをカウントし、要約を報告します。

$ strace -c ls
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 25.00    0.000125          21         6           mmap
 20.00    0.000100          25         4           open
 15.00    0.000075          25         3           read
 10.00    0.000050          17         3           close
------ ----------- ----------- --------- --------- ----------------
100.00    0.000500                    45         5 total

-t

トレースの各行の先頭に時刻を付けます。

$ strace -t ls
14:15:23 execve("/bin/ls", ["ls"], 0x7ffc8e5bb4a0 /* 58 vars */) = 0
14:15:23 brk(NULL)                      = 0x55a8a9899000
14:15:23 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

使用例

プログラムを最初から最後までトレースする

$ strace ls -l
execve("/bin/ls", ["ls", "-l"], 0x7ffc8e5bb4a0 /* 58 vars */) = 0
brk(NULL)                               = 0x55a8a9899000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
...

特定のシステムコールをトレースする

$ strace -e trace=open,read,write ls
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\23\2\0\0\0\0\0"..., 832) = 832
write(1, "file1.txt  file2.txt  file3.txt\n", 32) = 32

実行中のプロセスにアタッチして出力をファイルに保存する

$ strace -p 1234 -o process_trace.log
strace: Process 1234 attached
^C
$ cat process_trace.log
read(4, "data from socket", 1024)       = 16
write(1, "data from socket", 16)        = 16

ヒント:

システムコールのフィルタリング

-e trace= を使用して特定のシステムコールに焦点を当てます。例えば、-e trace=network はネットワーク関連の呼び出しのみを表示し、接続の問題をデバッグしやすくします。

パフォーマンスの問題を理解する

-c を使用して各システムコールにかかる時間の要約を取得します。これにより、アプリケーションでどのシステムコールが最も時間がかかっているかを特定できます。

子プロセスをトレースする

子プロセスをフォークするプログラムをトレースする場合は、常に -f を使用してください。これがないと、親プロセスのアクティビティしか見えません。

出力の冗長性を減らす

大きなファイルやバッファの場合、-s の後に数字を付けて文字列出力の長さを制限します。例えば、-s 100 は文字列を100文字に制限します。

トレースにタイムスタンプを付ける

-t または -tt(マイクロ秒精度の場合)を追加してトレースにタイムスタンプを含めると、イベントを他のログと関連付けるのに役立ちます。

よくある質問

Q1. strace と ltrace の違いは何ですか?

A. strace はシステムコール(プログラムとカーネルの間の相互作用)をトレースし、ltrace はライブラリコール(プログラムとライブラリの間の相互作用)をトレースします。

Q2. root 権限が必要なプログラムをトレースするにはどうすればよいですか?

A. sudo で strace を実行します:sudo strace command。root が所有する実行中のプロセスにアタッチするには、sudo strace -p PID を使用します。

Q3. strace でトレースすると、プログラムの実行が非常に遅くなるのはなぜですか?

A. トレースはすべてのシステムコールを傍受するため、大きなオーバーヘッドが追加されます。これは正常な動作であり、タイミング結果を解釈する際に考慮する必要があります。

Q4. ファイル関連の操作だけを見るにはどうすればよいですか?

A. strace -e trace=file command を使用して、ファイル関連のシステムコールのみを表示します。

Q5. strace はマルチスレッドアプリケーションをトレースできますか?

A. はい、strace -f を使用してスレッド(Linux ではプロセスとして実装されています)をフォローできます。

参考文献

https://man7.org/linux/man-pages/man1/strace.1.html

改訂履歴