Sử dụng strace để debug trên linux

  • Tuesday 21/04/2020

Sử dụng strace để debug trên linux

Trên linux có một công cụ vô cùng hữu ích để debug một process đang chạy gọi là strace. Nhờ có strace mà chúng ta có thể dễ dàng biết được một số thông tin như:

  • Tại sao chương trình stuck
  • Cái gì làm tốn thời gian (readfile, network…)
  • Vô vàn các thông tin thú vị khác

Strace (chắc là) viết tắt của system trace, có nhiệm vụ theo dõi các system call đến hệ thống của linux

Cách dùng dễ nhất:

strace -p <PID>

PID là process id của live process, sau đó strace sẽ cho bạn biết những system call nào đang đc chạy. Ví dụ mình có một process viết bằng go chạy lấy nội dung từ google xuống, strace sẽ cho thông tin

futex(0x927f48, FUTEX_WAIT, 0, NULL)    = 0
epoll_wait(4, [{EPOLLIN|EPOLLOUT, {u32=3290502472, u64=139843130692936}}], 128, 0) = 1
epoll_wait(4, [{EPOLLIN|EPOLLOUT, {u32=3290502472, u64=139843130692936}}], 128, -1) = 1
futex(0x9275b0, FUTEX_WAKE, 1)          = 1
read(5, "1\333Pu\211_\213\201\35\212\307\6(^\355 \260=HF[/\220\"\17\220\214G8\3\342\271"..., 4096) = 1294
futex(0xc8200c4108, FUTEX_WAKE, 1)      = 1
futex(0xc820024908, FUTEX_WAKE, 1)      = 1
read(5, 0xc820104000, 4096)             = -1 EAGAIN (Resource temporarily unavailable)
write(3, "GET / HTTP/1.1\r\nHost: google.com"..., 91) = 91
futex(0x927f48, FUTEX_WAIT, 0, NULL)    = 0
futex(0x927f48, FUTEX_WAIT, 0, NULL)    = 0
futex(0x927f48, FUTEX_WAIT, 0, NULL)    = 0
epoll_wait(4, [{EPOLLIN|EPOLLOUT, {u32=3290502472, u64=139843130692936}}], 128, 0) = 1
epoll_wait(4, [{EPOLLOUT, {u32=3290502472, u64=139843130692936}}], 128, -1) = 1
epoll_wait(4, [{EPOLLIN|EPOLLOUT, {u32=3290502856, u64=139843130693320}}], 128, -1) = 1
futex(0x9275b0, FUTEX_WAKE, 1)          = 1
read(3, "HTTP/1.1 302 Found\r\nCache-Contro"..., 4096) = 477
futex(0xc820024908, FUTEX_WAKE, 1)      = 1
read(3, 0xc8200e4000, 4096)             = -1 EAGAIN (Resource temporarily unavailable)
write(5, "GET /?gfe_rd=cr&ei=MEyDV_2_F_Hd8"..., 161) = 161

Các bạn có thể dễ dàng thấy các system call liên quan đến http/net như epoll hay là write.

Thêm flag -c vào các bạn có thể biết system call nào đang take time:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 58.29    0.024293          75       323         4 futex
 28.79    0.012000       12000         1         1 restart_syscall
 11.56    0.004817          32       151           epoll_wait
  0.73    0.000305          61         5           select
  0.63    0.000263           2       129        56 read
  0.00    0.000000           0        39           write
  0.00    0.000000           0         1           sched_yield
------ ----------- ----------- --------- --------- ----------------
100.00    0.041678                   649        61 total

Dựa vào strace cũng có thể biết một process mở file nào, ví dụ với mysql

$ strace mysql 2>&1  | grep 'open' | grep '.cnf'
open("/etc/mysql/my.cnf", O_RDONLY|O_LARGEFILE) = 3
open("/home/sonots/.my.cnf", O_RDONLY|O_LARGEFILE) = 3
4.6/5 - (64 bình chọn)