プロセスのシステムコールをトレースする strace

ALL
スポンサーリンク

Linuxで指定のプロセスのシステムコールをトレースするツール、straceの使い方です。
例えば、プロセスがどんなライブラリをロードしたかや、どんなファイルをオープン・読み書きしたかが分かります。

インストールは以下で行います。

ubuntu
apt-get install strace
CentOS
yum install strace

説明用のテストコードです。
gcc -o test test.c
を実行して下さい。実行ファイル test が出来ます。

test.c

include <stdio.h>
void main( void ){
  FILE *fp;
  int i;
  fp = fopen( "./test.in" , "r" );
  fscanf( fp , "value=%d\n" , &i );
  fclose( fp );
  printf( "i=%d\n" , i);
  fp = fopen( "./test.out" , "a" );
  fprintf( fp , "value=%d\n" , i );
  fclose( fp );
}

では、test を実行し、そのシステムコールをトレースします。
strace に test を指定して実行すると、以下のように色々と表示されます。

$ strace ./test
execve("./test", ["./test"], [/* 22 vars */]) = 0
brk(0)                                  = 0x1251000
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) = 0x7f55c775d000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=83020, ...}) = 0
mmap(NULL, 83020, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f55c7748000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1845024, ...}) = 0
mmap(NULL, 3953344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f55c7177000
mprotect(0x7f55c7332000, 2097152, PROT_NONE) = 0
mmap(0x7f55c7532000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bb000) = 0x7f55c7532000
mmap(0x7f55c7538000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f55c7538000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f55c7747000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f55c7745000
arch_prctl(ARCH_SET_FS, 0x7f55c7745740) = 0
mprotect(0x7f55c7532000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7f55c775f000, 4096, PROT_READ) = 0
munmap(0x7f55c7748000, 83020)           = 0
brk(0)                                  = 0x1251000
brk(0x1272000)                          = 0x1272000
open("./test.in", O_RDONLY)             = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=9, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f55c775c000
read(3, "value=99\n", 4096)             = 9
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f55c775c000, 4096)            = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f55c775c000
write(1, "i=99\n", 5i=99
)                   = 5
open("./test.out", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=48, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f55c775b000
fstat(3, {st_mode=S_IFREG|0664, st_size=48, ...}) = 0
lseek(3, 48, SEEK_SET)                  = 48
write(3, "value=99\n", 9)               = 9
close(3)                                = 0
munmap(0x7f55c775b000, 4096)            = 0

例えば以下のようにすると、ファイルオープンだけを表示します。
strace はトレース結果を標準エラー出力に吐き出すので、2>&1 で標準出力にリダイレクトしています。

$ strace ./test 2>&1 | grep -e ^open -e ^Error

例えば、出力結果が下記のようになります。
/etc/ld.so.cache,/lib/x86_64-linux-gnu/libc.so.6 が実行されていることがわかります。
( O_CLOEXEC より)
また test.c 内のコードの通り、test.in が読みだされ(O_RDONLYより)、test.out へ出力(O_WRONLY)されていることがわかります。

open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("./test.in", O_RDONLY)             = 3
open("./test.out", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

既に実行されているプロセスもトレース出来ます。
rootでトレースしたいプロセスのPIDを以下のように指定して実行します。

# strace -p プロセスID

例えば、以下のように実行すると。PIDが 3838 のプロセスのファイルオープンだけを表示します。

# strace -p 3838 2>&1 | grep -e ^open -e ^Error

参考:
チュートリアル:nagios(check_http)でIWSSを監視する
strace(1): trace system calls/signals – Linux man page

コメント