Linuxデバッグコマンド strace の基本的な使い方

プロセスに attach してトレースするデバッグコマンド strace の基本的な使い方です。


1. 実行コマンドをトレースする

$ strace ls
execve("/bin/ls", ["ls"], [/* 46 vars */]) = 0
brk(0)                                  = 0x1ab9000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcf695fb000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=102786, ...}) = 0
mmap(NULL, 102786, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcf695e1000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/librt.so.1", O_RDONLY)       = 3
(省略)


2. 実行中のプロセスをトレースする
p オプションで PID を指定して strace します。

$ strace -p 2097

権限のないプロセスを strace すると、以下のようなエラーになります。

$ strace -p 2129
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted


3. 特定のシステムコールのみをトレースする
特定のシステムコールに絞ってトレースする場合は、 e オプションを使用します。
サンプルとして、システムコール open に絞ってトレースしてみます。

$ strace -e open ls
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/librt.so.1", O_RDONLY)       = 3
open("/lib/libselinux.so.1", O_RDONLY)  = 3
open("/lib/libacl.so.1", O_RDONLY)      = 3
open("/lib/libc.so.6", O_RDONLY)        = 3
(省略)

複数のシステムコールをトレースする場合は、以下のような感じです。

$ strace -e trace=open,read ls
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/librt.so.1", O_RDONLY)       = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220!\0\0\0\0\0\0"..., 832) = 832
open("/lib/libselinux.so.1", O_RDONLY)  = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20Y\0\0\0\0\0\0"..., 832) = 832


4. トレース結果をファイルに出力する
o オプションでトレース結果を出力するファイル名を指定します。

$ strace -o strace-output.txt ls

p プロセスと一緒に使うと、ファイルに出力しながら実行中のプロセスをトレースすることができます。

$ strace -p 2097 -o strace-output.txt
$ tail -f strace-output.txt


5. トレース結果にタイムスタンプを出力する
t オプションでシステムコールの実行時間が出力されます。

$ strace -t ls
17:43:25 execve("/bin/ls", ["ls"], [/* 47 vars */]) = 0
17:43:25 brk(0)                         = 0x8ad000
17:43:25 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
17:43:25 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb41137b000
17:43:25 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)

r オプションでシステムコールが処理にかかった時間が出力されます。

$ strace -r ls
     0.000000 execve("/bin/ls", ["ls"], [/* 47 vars */]) = 0
     0.000287 brk(0)                    = 0x1dab000
     0.000052 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
     0.000057 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffadfb22000
     0.000049 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)


6. トレース結果の統計情報(サマリー)を出力する
c オプションで統計情報が出力されます。

$ strace -c ls
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  -nan    0.000000           0        11           read
  -nan    0.000000           0         4           write
  -nan    0.000000           0        26         1 open
  -nan    0.000000           0        27           close
  -nan    0.000000           0        25           fstat
  -nan    0.000000           0        39           mmap
  -nan    0.000000           0        16           mprotect
  -nan    0.000000           0         4           munmapstrace コマンドを使うと、
  -nan    0.000000           0         3           brk
  -nan    0.000000           0         2           rt_sigaction
  -nan    0.000000           0         1           rt_sigprocmask
  -nan    0.000000           0         2           ioctl
  -nan    0.000000           0         9         9 access
  -nan    0.000000           0         1           execve
  -nan    0.000000           0         1           fcntl
  -nan    0.000000           0         2           getdents
  -nan    0.000000           0         1           getrlimit
  -nan    0.000000           0         1           statfs
  -nan    0.000000           0         1           arch_prctl
  -nan    0.000000           0         3         1 futex
  -nan    0.000000           0         1           set_tid_address
  -nan    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                   181        11 total


strace コマンドを使うと、何気に使っているコマンドが、どのようなシステムコールやライブラリを呼び出しているかトレースできるので意外な発見があるかもしれません。
他にも様々なオプションがあるので、いろいろ試してみると勉強になると思います。