使用ltrace、strace跟蹤Linux進程事件,輔助分析疑難雜症
來源:互聯網
上載者:User
[原帖地址: http://hi.baidu.com/higkoo/blog/item/36ab6cf3c47eefc60b46e003.html]今天,我們來瞭解一下怎樣使用ltrace、strace來跟蹤Linux進程事件。首先,瞄一眼ltrace、strace的說明:ltrace - A library call tracerstrace - trace system calls and signals下面我用C和C++的一個簡單例子來示範一下它們的用法,同時使用C和C++也有點對比的意味。main.c#include <stdio.h>int main(){ printf("Hello World !"); return 0;}main.cpp#include <iostream>int main(){ std::cout<<"Hello World !"<<std::endl; return 0;}有興趣的朋友可以先比較一下兩者產生的彙編代碼,彙編的內容和trance的結果有一定關聯。編譯彙編碼方式如下(由於百度部落格長度限制,不能傳附件,就不貼出來了):gcc -S ./main.c -o main.c.sg++ -S ./main.cpp -o main.cpp.s下一步,編譯二進位檔案:gcc ./main.c -o ./main_cg++ ./main.cpp -o ./main_cpp查看檔案main_c main_cpp屬性:ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped兩者運行結果相同,都是列印“Hello World !”後退出。下面,我們來看下trace結果。ltrace ./main_c__libc_start_main(0x400498, 1, 0x7fffeb89e8a8, 0x4004d0, 0x4004c0 <unfinished ...>printf("Hello World !") = 13Hello World !+++ exited (status 0) +++ltrace ./main_cpp __libc_start_main(0x400844, 1, 0x7fff01389398, 0x400880, 0x400870 <unfinished ...>_ZNSt8ios_base4InitC1Ev(0x600e2c, 65535, 0x7fff013893a8, 3, 0x31e1752350) = 2__cxa_atexit(0x40082c, 0, 0x400960, 3, 0x31e1752350) = 0_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(0x600d10, 0x400968, 0x7fff013893a8, 4, 0x31e1752370) = 0x600d10_ZNSolsEPFRSoS_E(0x600d10, 0x4006e0, 0, 0xfbad2a84, 0xffffffff <unfinished ...>_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(0x600d10, 0x4006e0, 0, 0xfbad2a84, 0xffffffffHello World !) = 0x600d10_ZNSt8ios_base4InitD1Ev(0x600e2c, 0, 0x31e1752370, -1, 0x2b2e79280530) = 3+++ exited (status 0) +++相比而已,C語言真簡潔!下面再看一下strace的結果(由於篇幅限制,省略了部分資料):strace ./main_cexecve("./main_c", ["./main_c"], [/* 30 vars */]) = 0brk(0) = 0x1a9d4000uname({sys="Linux", node="performance106", ...}) = 0access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY) = 3fstat(3, {st_mode=S_IFREG|0644, st_size=68624, ...}) = 0mmap(NULL, 68624, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2afefc5f6000close(3) = 0open("/lib64/libc.so.6", O_RDONLY) = 3read(3, "/177ELF/2/1/1/0/0/0/0/0/0/0/0/0/3/0>/0/1/0/0/0/220/332A/3411/0/0/0"..., 832) = 832mprotect(0x31e154d000, 2097152, PROT_NONE) = 0close(3) = 0arch_prctl(ARCH_SET_FS, 0x2afefc608210) = 0write(1, "Hello World !", 13Hello World !) = 13exit_group(0)strace ./main_cppexecve("./main_cpp", ["./main_cpp"], [/* 30 vars */]) = 0brk(0) = 0x1d954000mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b4f71efd000uname({sys="Linux", node="performance106", ...}) = 0access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY) = 3fstat(3, {st_mode=S_IFREG|0644, st_size=68624, ...}) = 0close(3) = 0open("/usr/lib64/libstdc++.so.6", O_RDONLY) = 3arch_prctl(ARCH_SET_FS, 0x2b4f71f11530) = 0mprotect(0x31e121b000, 4096, PROT_READ) = 0munmap(0x2b4f71efe000, 68624) = 0fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b4f71efe000write(1, "Hello World !/n", 14Hello World !) = 14exit_group(0) = ? 從系統調用過程來看,最終方式是相同的,但C++過程繁瑣一些。 上述樣本是捕捉可執行程式的執行過程,同理也可以捕捉服務程式內部正在執行的事件。 譬如Nginx、Apache、Python等服務當前做了哪些事情,當遇到異常時非常有參考階段。 由於Java使用了自己的虛擬機器,必須使用Java對應的監控工具才行(如Jprofile、Jconsole、JvisualVM等)。用ltrace進行跟蹤,會收到“Cannot attach to pid 18663: Operation not permitted”。 分析過程一般還需要用到 truss、gdb、pstack、pfiles、top、lsof、pmap、netstat、ps 等指令共同分析。