4/12/2019

strace

1. STRACE란? 

strace는 SunOS에서 System Call을 Trace를 하기위해서 만들어진 Debug Tool이며, 이를 이용하여 실행중인 Program도 Trace가 가능하다.


$ sudo apt-get install strace 


  https://en.wikipedia.org/wiki/Strace

1.1 STRACE 기본사용법 


$ strace -h
usage: strace [-CdffhiqrtttTvVwxxy] [-I n] [-e expr]...
              [-a column] [-o file] [-s strsize] [-P path]...
              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]
   or: strace -c[dfw] [-I n] [-e expr]... [-O overhead] [-S sortby]
              -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]

Output format:
  -a column      alignment COLUMN for printing syscall results (default 40)
  -i             print instruction pointer at time of syscall
  -o file        send trace output to FILE instead of stderr
  -q             suppress messages about attaching, detaching, etc.
  -r             print relative timestamp
  -s strsize     limit length of print strings to STRSIZE chars (default 32)
  -t             print absolute timestamp
  -tt            print absolute timestamp with usecs
  -T             print time spent in each syscall
  -x             print non-ascii strings in hex
  -xx            print all strings in hex
  -y             print paths associated with file descriptor arguments
  -yy            print ip:port pairs associated with socket file descriptors

Statistics:
  -c             count time, calls, and errors for each syscall and report summary
  -C             like -c but also print regular output
  -O overhead    set overhead for tracing syscalls to OVERHEAD usecs
  -S sortby      sort syscall counts by: time, calls, name, nothing (default time)
  -w             summarise syscall latency (default is system time)

Filtering:
  -e expr        a qualifying expression: option=[!]all or option=[!]val1[,val2]...
     options:    trace, abbrev, verbose, raw, signal, read, write
  -P path        trace accesses to path

Tracing:
  -b execve      detach on execve syscall
  -D             run tracer process as a detached grandchild, not as parent
  -f             follow forks
  -ff            follow forks with output into separate files
  -I interruptible
     1:          no signals are blocked
     2:          fatal signals are blocked while decoding syscall (default)
     3:          fatal signals are always blocked (default if '-o FILE PROG')
     4:          fatal signals and SIGTSTP (^Z) are always blocked
                 (useful to make 'strace -o FILE PROG' not stop on ^Z)

Startup:
  -E var         remove var from the environment for command
  -E var=val     put var=val in the environment for command
  -p pid         trace process with process id PID, may be repeated
  -u username    run command as username handling setuid and/or setgid

Miscellaneous:
  -d             enable debug output to stderr
  -v             verbose mode: print unabbreviated argv, stat, termios, etc. args
  -h             print help message
  -V             print version


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

1.2 /proc를 이용하여 동작중인 Process 확인


$ sudo cat /proc/550/maps  // 실행과 관련된 공유라이브러리 확인 
$ sudo cat /proc/550/status  // Process 상태확인 
$ readelf -h /proc/550/exe    // 실행파일 확인 
$ readelf -s /proc/550/exe    // symbol table 확인     


1.3  PID 기반으로 STRACE 사용  

동작 중이 Process 기반으로 아래와 같이 PID를 넣어 직접 Profile을 해보고 Debug을 해봅니다.


  • 상위 동작 중인 PID 기반으로 Debug

$ strace -p 550 -f -t -s 65535 // -p PID -f fork된 밑에 process들도 같이 분석, -t timestamp 출력  -s string 사이즈 변경 
...........
[pid   994] 11:25:13 pselect6(0, NULL, NULL, NULL, {0, 10000000}, NULL) = 0 (Timeout)
[pid   994] 11:25:13 fstat(31, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
[pid   994] 11:25:13 fstat(31, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
[pid   994] 11:25:13 read(31, "count 180\nunhandled 0\nlast_unhan"..., 1024) = 42
...............


$ strace -p 550 -f -tt  // -p PID -f fork된 밑에 process들도 같이 분석, -t timestamp 출력 
[pid   994] 11:30:52.563464 fstat(31, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
[pid   994] 11:30:52.563761 fstat(31, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
[pid   994] 11:30:52.564047 read(31, "count 180\nunhandled 0\nlast_unhan"..., 1024) = 42


  • System Call 함수의 호출의 통계
간단히 본인이 원하는 System Call 함수의 Profile 가능하며, 통계를 내어 분석도 가능

$ strace -cp 550 -f  // -p PID -f fork된 밑에 process들도 같이 분석, -c count call
strace: Process 550 attached with 4 threads
^Cstrace: Process 550 detached
strace: Process 743 detached
strace: Process 994 detached
strace: Process 995 detached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 98.67    0.488000        1132       431           pselect6
  0.94    0.004653          12       382           sendto
  0.13    0.000666           2       382           openat
  0.10    0.000495           1       382           close
  0.09    0.000457           1       764           fstat
  0.06    0.000310           1       382           read
  0.00    0.000000           0         4         2 futex
------ ----------- ----------- --------- --------- ----------------
100.00    0.494581                  2727         2 total


1.4  STRACE 사용

보통 아래와 같이 본인이 trace하고 싶은 app과 함께 같이 사용을 하며, 현재 test program을 없기에, ps command를 분석한다.

$ strace -c >/dev/null ps                     // ps program 내부 system call 분석 ,  ps의 내용은 /dev/null 출력 
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 38.53    0.012719          46       279           read
 24.46    0.008074          31       260         6 open
 13.92    0.004595          18       254           close
  9.01    0.002973          25       119         3 stat64
  3.72    0.001227          29        43           mmap2
  2.82    0.000932          29        32           mprotect
  1.75    0.000577         289         2           getdents64
  1.25    0.000412          16        25           fstat64
  1.17    0.000385          14        28           lseek
  0.99    0.000328          14        24           rt_sigaction
  0.99    0.000327          20        16        15 access
  0.31    0.000102          51         2         2 statfs
  0.31    0.000101          51         2           munmap
  0.18    0.000061          15         4         3 ioctl
  0.11    0.000035          12         3           brk
  0.09    0.000031          16         2           _llseek
  0.06    0.000021          21         1           cacheflush
  0.05    0.000018          18         1           futex
  0.05    0.000016          16         1           ugetrlimit
  0.05    0.000015          15         1           set_tid_address
  0.04    0.000014          14         1           rt_sigprocmask
  0.04    0.000014          14         1           set_tls
  0.04    0.000013          13         1           geteuid32
  0.04    0.000013          13         1           set_robust_list
  0.03    0.000009           9         1           write
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           uname
------ ----------- ----------- --------- --------- ----------------
100.00    0.033012                  1106        29 total



$ strace -e open >/dev/null ps       // ps 프로그램에서 open만 검색 
open("/etc/ld.so.preload", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/arm-linux-gnueabihf/libarmmem.so", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libprocps.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libsystemd.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/liblzma.so.5", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/arm-linux-gnueabihf/liblz4.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libpcre.so.3", O_RDONLY|O_CLOEXEC) = 3
open("/lib/arm-linux-gnueabihf/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
.......


  https://hokstad.com/5-simple-ways-to-troubleshoot-using-strace
  http://www.brendangregg.com/perf.html
  https://brunch.co.kr/@alden/12
  http://linuxspot.tistory.com/253