两个都strace和ltrace是在Linux上调试和故障排除程序的强大命令行工具:strace捕获和记录流程和收到的信号的所有系统呼叫,而ltrace对于库呼叫也是如此。
如果程序的行为与您的预期不同,则可以使用这些工具来看到“窗帘后面”,并可能会了解正在发生的事情。
不过,请注意。当您使用这些命令中的任何一个时,您最终都会得到很多输出要查看。尽管如此,这可以告诉您很多关于过程的工作原理,有时还可以为您提供重要的见解。
strace
跑步strace反对程序,使用如下所示的命令 -strace命令随后是程序名称。下面的输出已缩短。
$ strace执行(“/usr/bin/who”,[“ who”],0x7ffe889f45c0/ * 41 vars */)= 0 brk(null)= 0x55E7D6720000 Arch_prctl(0x3001/ * Arch _ Arch _ Arch _?= -1 eInval(无效参数)access(“/etc/ld.so..preload”,r_ok)= -1 enoent(no uke file或directory)openat(at_fdcwd,“ /etc/ld.so.so.cache”,o_rdonlyly|O_CLOEXEC) = 3 newfstatat(3, “”, {st_mode=S_IFREG|0644, st_size=60195, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 60195, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fd1ba4d7000 close(3) …
上面的命令运行这谁命令并报告了它发出的系统调用。每行的开始(例如,执行,,,,BRK和Arch_prctl)显示正在调用系统呼叫。
跑步strace反对运行过程以查看其在做什么,将命令与-p选项随后是过程ID。请注意strace附加过程后,输出从下面的第三行开始。
$ strace -p 34512 strace:Process 34512附加wait4(-1,[{wirsxited(s)&& wexitstatus(s)== 0}],0,null)= 34516…
注意:您不能重定向strace通过管道命令,但是您可以使用该管道将其发送到文件-o选项。在下面的示例中,日期显示命令输出。之后,输出文件的顶部使用头命令。
$ strace -o outputfile日期星期二5月3日03:33:52 pm EDT 2022 $ head -10 outputfile execve(“/usr/bin/date”,[“ date”],0x7ffc30f3bd00/ * 41 vars */)= 0 BRK(null)= 0x55E78C077000 Arch_prctl(0x3001/ * Arch _ ??? */,0x7ffe52bf2ec0)= -1 einval(nivalid grignt)acckess(“/etc/etc/etc/etc/etc/ld.so.preload”或Directory)openat(at_fdcwd,“ /etc/ld.so.cache”,o_rdonly | o_cloexec)= 3 newfstatat(3,3,“”,{st_mode = s_ifreg | 0644,st_size,st_size = 60195,...},...0 mmap(null,60195,prot_read,map_private,3,0)= 0x7f589661b000关闭(3)= 0 Openat(at_fdcwd,“/lib64/libcc.so.so.6”177f \ 2 \ 1 \ 1 \ 1 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 3 \ 0> \ 0> \ 0 \ 1 \ 1 \ 0 \ 0 \ 0pp \ 0pp \ 0pp \ 4 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0\ 0” ...,832)= 832
请记住,您正在查看系统电话,而不是程序。So, don’t be surprised if you don’t recognize “execve”, “brk”, “arch_prctl”, etc. You can, however, examine the man pages for these system calls if you want to learn more about what they do and how they work. Notice that the man pages for system calls come from Section 2 of the man pages.
$ MAN EXECVE |负责人-4执行(2)Linux程序员手册执行(2)<==名称执行 - 执行程序
使用的另一种有用的方法strace命令是添加-C选项。当您执行此操作时,输出提供了一个系统调用的摘要,该系统呼叫按在每个系统呼叫上花费的时间百分比(最大的第一)。如您在下面的示例中所看到的,花了更多时间mmap(映射文件)比其他任何系统调用。
$ strace -c日期星期二5月3日03:40:25 PM EDT 2022%的时间秒/次通话错误syscall syscall ————————————————————————————————————————————————————————————— 28.49 0.000106 11 9 mmap 12.10 0.000045 11 4 openat 10.22 0.000038 9 4 mprotect 9.95 0.000037 6 6 newfstatat 8.87 0.000033 8 4 pread64 6.72 0.000025 4 6 close 4.57 0.000017 5 3 read 3.49 0.000013 13 1 1 access 2.960.000011 11 1 munmap 2.69 0.000010 10 1 write 2.15 0.000008 2 3 brk 1.88 0.000007 3 2 1 arch_prctl 1.34 0.000005 5 1 set_tid_address 1.34 0.000005 5 1 set_robust_list 1.08 0.000004 4 1 lseek 1.08 0.000004 4 1 prlimit64 1.08 0.000004 4 1 getrandom 0.00 0.000000 0 1 execve———————————————————————————————————— 100.00 0.000372 7 50 2总计
ltrace
这ltrace命令的工作与strace,但是检查库电话。在下面的示例中,我们看到ltrace使用基本的语法与strace。
第一个示例查看了库的调用谁命令。
$ ltrace who strrchr(“who”, ‘/’) = nil setlocale(LC_ALL, “”) ="en_US.UTF-8" bindtextdomain(“coreutils”, “/usr/share/locale”) ="/usr/share/locale" textdomain(“coreutils”) ="coreutils" __cxa_atexit(0x560c6532d220, 0, 0x560c65334940, 0) = 0 getopt_long(1, 0x7ffc1f74a468, “abdlmpqrstuwHT”, 0x560c65334960, nil) = -1 setlocale(LC_TIME, nil) ="en_US.UTF-8" strlen(“en_US.UTF-8”) = 11 __memcpy_chk(0x7ffc1f74a1f0, 0x560c65bf6370, 12, 257) = 0x7ffc1f74a1f0 strcmp(“en_US.UTF-8”, “POSIX”) = 21 utmpxname(0x560c65331016, 1, 0x560c65331266, 0x560c65331266) = 0 setutxent(0x560c6533101e, 0x7f2330570cc0, 5, 0) = 1 …
下一个示例显示了库的呼叫运行过程:
$ ltrace -p 35243 sigemptyset(<>)= 0 sigemptyset(<>)= 0 sigaction(sigint,{nil,<>,0x3f679854,0x560643c72e53},,,,21523, 0x7ffe3f679870) = 0 malloc(48) = 0x56064548b020 strlen(“LINES”) = 5 malloc(6) = 0x56064548dfb0 strcpy(0x56064548dfb0, “LINES”) = 0x56064548dfb0 strlen(“LINES”) = 5 malloc(6)
发送ltrace输出到文件需要使用-o选项。
$ ltrace -o outputfile date Tue May 3 04:17:30 PM EDT 2022 $ head -10 outputfile strrchr(“date”, ‘/’) = nil setlocale(LC_ALL, “”) ="en_US.UTF-8" bindtextdomain(“coreutils”, “/usr/share/locale”) ="/usr/share/locale" textdomain(“coreutils”) ="coreutils" __cxa_atexit(0x55e8afe3f280, 0, 0x55e8afe4e000, 0) = 0 getopt_long(1, 0x7ffdc8986948, “d:f:I::r:Rs:u”, 0x55e8afe4e920, nil) = -1 nl_langinfo(0x2006c, 0x7ffdc8986948, 0, 0) = 0x7f3afe645435 getenv(“TZ”) = nil malloc(128) = 0x55e8b05b0440 clock_gettime(0, 0x7ffdc8986740, 1, 145) = 0
请注意,图书馆呼叫的人页面来自该人页面的第3节。
$ man strrchr |头-4 strchr(3)Linux程序员手册strchr(3)<==名称strchr,strrchr,strchrnul-在字符串中找到字符
$ MAN Strlen |头-4 strlen(3)Linux程序员手册strlen(3)名称strlen-计算字符串的长度
使用-C选项ltrace,就像strace,首先以最长的运行时间订购列表。
$ ltrace -c pwd/home/shs%秒秒usecs/呼叫功能————————————————————————————————————————— 16.02 0.0002 0.000428 4281 setlocale 10.82 0.000289 72 4 __freading 7.93 0.000212 212 1 puts 6.74 0.000180 90 2 fclose 5.39 0.000144 72 2 fileno 5.39 0.000144 144 1 getcwd 5.35 0.000143 71 2 __fpending 5.28 0.000141 70 2 fflush 4.79 0.000128 128 1 free 4.64 0.000124 124 1 bindtextdomain 4.49 0.000120 1201 exit_group 4.49 0.000120 120 1 getenv 4.19 0.000112 112 1 getopt_long 4.00 0.000107 107 1 textdomain 3.97 0.000106 106 1 strrchr 3.93 0.000105 105 1 __cxa_atexit 2.58 0.000069 69 1 __cxa_finalize ——— —————- —————- ———----—————————— 100.00 0.002672 24总计
安装strace和ltrace
这样的命令用于安装strace:
$ sudo apt install strace#debian/ubuntu $ sudo yum安装strace#rhel/centos $ sudo dnf dnf安装strace#fedora
相似地,ltrace将使用此类命令安装:
$ sudo apt install ltrace#debian/ubuntu $ sudo yum安装ltrace#rhel/centos $ sudo dnf install ltrace#fedora
包起来
这俩strace和ltrace命令提供大量的输出,但可以证明非常有用,尤其是一旦您习惯了它们提供的输出。