`

(转)Linux利器 strace

阅读更多
原文:http://www.perfgeeks.com/?p=501

今天才发现strace是个好东西呀
strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。

strace使用参数
-p 跟踪指定的进程
-f 跟踪由fork子进程系统调用
-F 尝试跟踪vfork子进程系统调吸入,与-f同时出现时, vfork不被跟踪
-o filename 默认strace将结果输出到stdout。通过-o可以将输出写入到filename文件中
-ff 常与-o选项一起使用,不同进程(子进程)产生的系统调用输出到filename.PID文件
-r 打印每一个系统调用的相对时间
-t 在输出中的每一行前加上时间信息。 -tt 时间确定到微秒级。还可以使用-ttt打印相对时间
-v 输出所有系统调用。默认情况下,一些频繁调用的系统调用不会输出
-s 指定每一行输出字符串的长度,默认是32。文件名一直全部输出
-c 统计每种系统调用所执行的时间,调用次数,出错次数。
-e expr 输出过滤器,通过表达式,可以过滤出掉你不想要输出

应用场景
#1.跟踪你的web服务器系统调用
系统调用优化,也是web性能优化的一个较为重要的方向,尤其是在I/O密集型web应用的情况。我们这里的测试环境是CentOS5.4+Nginx+FastCGI。

<?php
//file:hello.php
define('DOCUMENT_ROOT', dirname(__FILE__));
include("hello.inc");
include("./hello.inc");
include(DOCUMENT_ROOT . "/hello.inc");
?>
#strace -f -F -o strace_nginx strace /wwwchroot/nginx/sbin/nginx -c /wwwchroot/nginx/nginx.conf
... (有部分不重要的数据影响排版,在这里使用...代替)
//--接受来自客户端的http请求
4165  recv(16, "GET /hello.php HTTP/1.1\r\nHost: f"..., 32768, 0) = 391
4165  epoll_ctl(9, EPOLL_CTL_MOD, 16, {EPOLLIN|EPOLLOUT|EPOLLET, {u32=3081162952, u64=698098541354471624}}) = 0
//--进行DNS查找
4165  getsockname(16, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("222.73.211.214")}, [16]) = 0
//--新建一个socket,连接Fast-CGI,端口号为9000
4165  socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 17
4165  ioctl(17, FIONBIO, [1])           = 0
4165  epoll_ctl(9, EPOLL_CTL_ADD, 17, {EPOLLIN|EPOLLOUT|EPOLLET, {u32=3081163048, u64=697886249710965032}}) = 0
4165  connect(17, {sa_family=AF_INET, sin_port=htons(9000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 )
4165  epoll_wait(9, {{EPOLLOUT, {u32=3081163048, u64=697886249710965032}}, {...}, 5\
12, 300000) = 2
4165  gettimeofday({1295420285, 130967}, NULL) = 0
4165  recv(16, 0xbfdd7d8b, 1, MSG_PEEK) = -1 EAGAIN (Resource temporarily unavailable)
4165  getsockopt(17, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
//--将用户http请求交给Fast-CGI
4165  writev(17, [{"\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\3\30\0\0\21\7GATEWA"..., 832}], 1) = 832
4165  epoll_wait(9, {{EPOLLIN|EPOLLOUT, {u32=3081163048, u64=697886249710965032}}}, 512, 300000) = 1
4165  gettimeofday({1295420285, 131559}, NULL) = 0
//--接收Fast-CGI响应
4165  recv(17, "\1\6\0\1\0V\2\0X-Powered-By: PHP/5.2.10"..., 65536, 0) = 112
4165  readv(17, [{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65424}], 1) = 0
4165  mmap2(NULL, 274432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7514000
4165  close(17)                         = 0
4165  munmap(0xb7514000, 274432)        = 0
//-- 响应客户端http请求,即http响应
4165  writev(16, [{"HTTP/1.1 200 OK\r\nServer: nginx/0"..., 228}, {"22\r\n", 4}, ..., 5) = 273
4165  write(5, "116.66.34.82 - - [19/Jan/2011:14"..., 191) = 191
4165  setsockopt(16, SOL_TCP, TCP_NODELAY, [1], 4) = 0
4165  recv(16, 0x9b024e8, 32768, 0)     = -1 EAGAIN (Resource temporarily unavailable)
...

通过这些,我们只能够大概地了解,Nginx这里启用了epoll。同时,还可以了解到Nginx和Fast-CGI底层是如何运作的。奇怪,hello.php文件中有三个inclue,即加载了三次文件,这里没有看到相应的i/o逻辑操作,是为什么呢?这是因为,Nginx并没解析处理PHP脚本,而是交给Fast-CGI去做这部事情了。

#strace -f -F -o php-cgi-strace /wwwchroot/php/bin/php-cgi --fpm-config /wwwchroot/php/etc/php-fpm.conf
//--接收来自Nginx发出的请求
4510  <... accept resumed> {sa_family=AF_INET, sin_port=htons(35983), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
4510  clock_gettime(CLOCK_MONOTONIC, {22638545, 869965681}) = 0
4510  poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
4510  read(3, "\1\1\0\1\0\10\0\0",   = 8
4510  read(3, "\0\1\0\0\0\0\0\0",    = 8
4510  read(3, "\1\4\0\1\0035\3\0",   = 8
4510  read(3, "\21\7GATEWAY_INTERFACECGI/1.1\17\5SERV"..., 824) = 824
4510  read(3, "\1\4\0\1\0\0\0\0",    = 8
4510  time(NULL)                        = 1295425149
//--加载请求资源文件hello.php
4510  lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www/ep/hello.php", {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
4510  clock_gettime(CLOCK_MONOTONIC, {22638545, 870893872}) = 0
4510  setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={60, 0}}, NULL) = 0
4510  rt_sigaction(SIGPROF, {0x835c120, [PROF], SA_RESTART}, {SIG_DFL, [], 0}, = 0
4510  rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, = 0
4510  time(NULL)                        = 1295425149
4510  open("/var/www/ep/hello.php", O_RDONLY) = 4
4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
4510  time(NULL)                        = 1295425149
4510  chdir("/var/www/ep")              = 0
4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
4510  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe7000
4510  read(4, "\n", 8192) = 29
4510  read(4, "", 8192)                 = 0
4510  read(4, "", 8192)                 = 0
4510  close(4)                          = 0
//--  加载hello.inc, 对应php代码include './hello.inc'
4510  getcwd("/var/www/ep"..., 4096)    = 12
4510  time(NULL)                        = 1295425149
4510  open("/var/www/ep/hello.inc", O_RDONLY) = 4
4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
4510  read(4, "\n", 8192) = 29
4510  read(4, "", 8192)                 = 0
4510  read(4, "", 8192)                 = 0
4510  close(4)                          = 0
4510  time(NULL)                        = 1295425149
//-- 加载hello.inc, 对应php代码include DOCUMENT_ROOT . '/hello.inc'
4510  lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
4510  lstat64("/var/www/ep/hello.inc", {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
4510  open("/var/www/ep/hello.inc", O_RDONLY) = 4
4510  fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
4510  read(4, "\n", 8192) = 29
4510  read(4, "", 8192)                 = 0
4510  read(4, "", 8192)                 = 0
4510  close(4)                          = 0
//-- 将响结果输出给Nginx,并且关闭连接
4510  write(3, "\1\6\0\1\0V\2\0X-Powered-By: PHP/5.2.10"..., 96) = 96
4510  setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
4510  write(3, "\1\3\0\1\0\10\0\0\0\0\0\0\0ere", 16) = 16
4510  shutdown(3, 1 /* send */)         = 0
4510  recv(3, "\1\5\0\1\0\0\0\0", 8, 0) = 8
4510  recv(3, "", 8, 0)                 = 0
4510  close(3)                          = 0

通过跟踪php-cgi,我们可以知道,相较与其它二种方法include ‘./hello.inc’的性能是最高的。这里看到strace输出都被截断了,如果你需要看到更多的输出,可以通过-s选项,让strace输出更多内容。

当你发现某个http请求造成CPU占用效骤然升高,你可以通过strace跟踪查找问题的根源。同时,你也可以通过strace -c统计监控你的优化是否生效
#2. MySQL执行语句列表
当发生个http请求的时候,很多时候希望得到这个http请求发生了多少次数据库SELECT操作,是否在同一个mysql connection连接里面完成。这里以访问本页为例子,通过strace来跟踪这些MySQL SELECT查询语句。

//-9514是mysqld的进程号,为了看到整条SQL语句,我们通过-s 1024希望输出更多内容
#strace -f -F -ff -o strace-mysqld -s 1024 -p 9514
#find . -name "strace-mysqld*" -type f -print |xargs grep -n "SELECT.*FROM wp_"
./strace-mysqld.19203:64:
read(19, "\3SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'", 72) = 72
./strace-mysqld.19203:165:
read(19, "\3SELECT * FROM wp_users WHERE user_login = 'admin'", 50) = 50
./strace-mysqld.19203:184:
read(19, "\3SELECT meta_key, meta_value FROM wp_usermeta WHERE user_id = 1", 63) = 63
./strace-mysqld.19203:295:
read(19, "\3SELECT option_value FROM wp_options WHERE option_name = 'rewrite_rules' LIMIT 1", 80) = 80
./strace-mysqld.19203:311:
read(19, "\3 SELECT   wp_posts.* FROM wp_posts  WHERE 1=1  AND wp_posts.ID = 501
     AND wp_posts.post_type = 'post'  ORDER BY wp_posts.post_date DESC ", 136) = 136
... (这里省去了一些)

分享到:
评论

相关推荐

    strace-4.5.

    《深入理解strace工具:基于strace-4.5.15版本的探索》 在Linux操作系统中,strace是一个非常实用的系统调用跟踪工具,它能够帮助开发者和系统...在实际工作中,不断探索和实践,strace将会成为我们不可或缺的利器。

    运维利器:万能的strace1

    `strace` 是一款强大的 Linux 系统诊断工具,它允许运维人员监控用户空间进程与内核之间的交互,包括系统调用、信号处理、进程状态变化等。在故障排查和问题诊断过程中,`strace` 提供了一种动态跟踪的方法,帮助...

    基于Linux调试工具strace与gdb的常用命令总结

    总的来说,strace和gdb是Linux环境下强大的调试利器,它们可以帮助开发者深入理解程序行为,定位问题,优化性能,对于任何Linux开发者来说都是必备的技能。通过熟练掌握这些工具,可以大大提高软件开发和维护的效率...

    Linux for ARM 调试软件集

    4. **其他可能包含的调试工具**:除了上述软件,Linux调试软件集可能还包括GDB(GNU Debugger)、Strace、Lsof、Syslog等工具。GDB是C/C++程序的调试利器,可以通过源代码级别的控制来跟踪和调试程序。Strace和Lsof...

    嵌入式Linux应用程序开发PPT

    10. **调试技术**:GDB、SystemTap、strace等工具是调试嵌入式Linux程序的利器,学习如何使用它们可以极大地提高开发效率。 通过本PPT的学习,初学者可以逐步掌握以上知识点,并建立起扎实的嵌入式Linux开发基础。...

    嵌入式Linux应用程序开发详解(华清远见)

    9. **调试技巧**:GDB、SystemTap、strace等工具是嵌入式开发者的利器,学会使用它们可以有效地定位和解决问题。 10. **持续学习和实践**:嵌入式Linux技术不断发展,新的硬件平台、框架和库不断涌现,保持对最新...

    练成Linux高手

    此外,Linux环境下的开发工具,如gcc/g++编译器、gdb调试器、valgrind内存检测工具,也是提升开发效率的利器。 对于系统监控和性能分析,工具如top、htop、iostat、vmstat、strace等能帮助你诊断和优化系统性能。...

    Linux课件ppt及常用命令汇总

    另外,还会涉及到环境变量的设置、shell脚本编写、cron定时任务的配置,甚至可能会涉及一些调试和性能监控的工具,如`strace`和`gdb`。 此外,Linux的哲学强调"一切皆文件",所以理解设备文件、符号链接、硬链接等...

    Linux一句话精彩回

    8. **问题排查**:`grep`用于在文件或输出中搜索特定模式,`logrotate`帮助管理日志文件,`strace`追踪系统调用和信号,`dmesg`显示内核消息,这些都是诊断问题的利器。 9. **脚本编程**:Linux shell脚本(bash)...

    【野火】《i.MX Linux开发实战指南》.pdf

    SQLite、web 服务器、Java 环境搭建、OpenCV 数字识别、进程、管道、信号、消息队列、共享内存、线程、POSIX 信号量、网络编程、套接字、GDB 调试利器、核心转储调试、函数调用栈、strace、HTTP 协议、CANopen 学习...

    LinuxOS课程练习代码(第一周汇总)

    此外,`grep`, `find`, `strace`等工具也是日常系统诊断的利器。 通过这个压缩包,学生可以实际操作这些代码,加深对Linux操作系统的理解和应用能力。同时,参考提供的链接http://edsionte.com/techblog/,可以找到...

    LINUX笔记

    `dmesg`显示系统启动时的内核消息,`strace`跟踪系统调用和信号,是调试程序的利器。 8. **脚本编程**:Linux支持使用bash或其他shell编写脚本自动化任务,掌握条件判断、循环、函数等基础语法,可以大大提高工作...

    Linux管理员指南

    9. **脚本编程**:bash脚本是Linux自动化运维的利器。通过编写shell脚本,可以实现批量任务执行、定时任务调度等。 10. **故障排查**:学习如何使用`dmesg`查看内核消息,`strace`跟踪系统调用,`gdb`调试程序,...

    strace_epitech:学科

    本文将深入探讨strace的工作原理、使用方法及其在实际问题中的应用,旨在帮助读者掌握这一强大的系统调试利器。 一、strace概述 strace是一个动态跟踪工具,用于监控系统调用和信号处理。它可以在运行时记录和显示...

    Linux指令速查手册

    `dmesg`显示内核消息,`journalctl`用于查看systemd日志,`strace`跟踪系统调用,`gdb`是强大的调试工具。 《Linux指令速查手册》中的每一个指令都配有详细的语法解释、参数说明和实例,确保读者能迅速上手并应用于...

    ARM架构Linux测试相关工具集合.zip

    除此之外,"strace"和"gdb"是调试工具中的两大利器。strace用于跟踪系统调用和信号,帮助分析进程与内核的交互,找出程序中可能存在的错误或者性能问题。gdb则是GNU项目下的一个源代码级别的调试器,它允许程序员在...

    软考网络工程师视频课件(二):linux服务器配置

    最后,视频可能还会涉及系统监控和故障排查工具,如top、htop、iostat、vmstat和strace,这些都是运维人员日常工作中用来诊断性能问题和排除故障的利器。 总的来说,这四个视频课件构成了一套完整的Linux服务器配置...

    五个 Linux 下用户空间的调试工具-技术 ◆ 学习_Linux1

    GDB提供断点、单步执行、变量观察、调用堆栈分析等功能,是深入调试复杂程序的利器。 这些工具各有优势,适用于不同的调试场景。在实际工作中,通常会结合使用多种工具,以便更全面地理解和解决问题。例如,`print`...

Global site tag (gtag.js) - Google Analytics