Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

system callのtraceについて

system call trace

起動プログラムからOSのシステムコールを呼び出される箇所をトレースするコマンドがあります。
strace / itrace / ktrace / kdumpなど。
単純なPHPのプログラムでは特にトレースする意味はないと思いますが、PHPのエクステンション作成やミドルウェア構築の時にはトレースして状態を確認してみるのが良いかと考えます。 今回はstraceの使い方についてまとめます。

使いそうなオプション

strace

オプション 意味
-c カウント数やコール、エラーなどを記録し、サマリーも表示
-e 特定のシステムコールのみ拾う
-f forkされた子プロセスも拾う
-F vforkを拾う
-T 処理にかかった時間を表示
-o ファイルに記録する
-p プロセスIDを指定する

通常の起動

strace httpd

execve("/usr/sbin/httpd", ["httpd"], [/* 16 vars */]) = 0
brk(0)                                  = 0x2ae87fab0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae879abe000
uname({sys="Linux", node="localhost.localdomain", ...}) = 0
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=111599, ...}) = 0
mmap(NULL, 111599, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ae879abf000
close(3)                                = 0
open("/lib64/libm.so.6", O_RDONLY)      = 3
(略)

処理にかかった時間を表示( -T )

strace -T httpd

execve("/usr/sbin/httpd", ["httpd"], [/* 16 vars */]) = 0 <0.001002>
brk(0)                                  = 0x2ac1fd186000 <0.000019>
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ac1ddf60000 <0.000021>
uname({sys="Linux", node="localhost.localdomain", ...}) = 0 <0.000018>
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory) <0.000033>
open("/etc/ld.so.cache", O_RDONLY)      = 3 <0.000026>
fstat(3, {st_mode=S_IFREG|0644, st_size=111599, ...}) = 0 <0.000020>
mmap(NULL, 111599, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ac1ddf61000 <0.000022>
close(3)                                = 0 <0.000019>
open("/lib64/libm.so.6", O_RDONLY)      = 3 <0.000034>
(略)

特定のシステムコールのみ拾う( -e )

strace -e write httpd

write(2, "(13)Permission denied: make_sock"..., 68(13)Permission denied: make_sock: could not bind to address [::]:80
) = 68
write(2, "(13)Permission denied: make_sock"..., 71(13)Permission denied: make_sock: could not bind to address 0.0.0.0:80
) = 71
write(2, "no listening sockets available, "..., 46no listening sockets available, shutting down
) = 46
write(2, "Unable to open logs\n", 20Unable to open logs
)   = 20

サマリー表示( -c ), forkを拾う( -f , -F )

strace -c -f -F httpd

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 34.33    0.000721           9        84           munmap
 31.43    0.000660           3       232           mmap
 15.81    0.000332           3       105           mprotect
  5.29    0.000111           1       131         6 open
  3.67    0.000077           1       144           read
  3.48    0.000073           7        11         6 connect
  3.10    0.000065           0       142           close
  1.62    0.000034           5         7           setsockopt
  1.29    0.000027           0       121           fstat
  0.00    0.000000           0         4           write
  0.00    0.000000           0        20         3 stat
  0.00    0.000000           0         1           lseek
  0.00    0.000000           0        12           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           readv
  0.00    0.000000           0         2         1 access
  0.00    0.000000           0        18           socket
  0.00    0.000000           0         3           sendto
  0.00    0.000000           0         1           sendmsg
  0.00    0.000000           0         9           recvmsg
  0.00    0.000000           0         5         2 bind
  0.00    0.000000           0         7           getsockname
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           uname
  0.00    0.000000           0        19           fcntl
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         1           getuid
  0.00    0.000000           0         1           getppid
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           gettid
  0.00    0.000000           0         4           futex
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.002100                  1099        18 total

トレース結果をファイルに保存( -o )

strace -c -f -F -o trace.txt httpd
※トレースした結果をtrace.txtに保存

プロセスIDを指定する( -p )

strace -p `ps auxww | grep 'httpd' | awk '{ print $2 }' | head -n 1`
※psなどの結果からプロセスIDを取得しstraceに流す

おまけ( -e execve )

strace -e execve -p PID
※不審なプロセスを調査する。
http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/012strace.html