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
コメント