Linux利器 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。

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

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

  1. #strace -f -F -o php-cgi-strace /wwwchroot/php/bin/php-cgi --fpm-config /wwwchroot/php/etc/php-fpm.conf
  2. //--接收来自Nginx发出的请求
  3. 4510 <... accept resumed> {sa_family=AF_INET, sin_port=htons(35983), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
  4. 4510 clock_gettime(CLOCK_MONOTONIC, {22638545, 869965681}) = 0
  5. 4510 poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
  6. 4510 read(3, "\1\1\0\1\0\10\0\0", 8) = 8
  7. 4510 read(3, "\0\1\0\0\0\0\0\0", 8) = 8
  8. 4510 read(3, "\1\4\0\1\0035\3\0", 8) = 8
  9. 4510 read(3, "\21\7GATEWAY_INTERFACECGI/1.1\17\5SERV"..., 824) = 824
  10. 4510 read(3, "\1\4\0\1\0\0\0\0", 8) = 8
  11. 4510 time(NULL) = 1295425149
  12. //--加载请求资源文件hello.php
  13. 4510 lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  14. 4510 lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  15. 4510 lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  16. 4510 lstat64("/var/www/ep/hello.php", {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
  17. 4510 clock_gettime(CLOCK_MONOTONIC, {22638545, 870893872}) = 0
  18. 4510 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={60, 0}}, NULL) = 0
  19. 4510 rt_sigaction(SIGPROF, {0x835c120, [PROF], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
  20. 4510 rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0
  21. 4510 time(NULL) = 1295425149
  22. 4510 open("/var/www/ep/hello.php", O_RDONLY) = 4
  23. 4510 fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
  24. 4510 time(NULL) = 1295425149
  25. 4510 chdir("/var/www/ep") = 0
  26. 4510 fstat64(4, {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
  27. 4510 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe7000
  28. 4510 read(4, "\n", 8192) = 29
  29. 4510 read(4, "", 8192) = 0
  30. 4510 read(4, "", 8192) = 0
  31. 4510 close(4) = 0
  32. //-- 加载hello.inc, 对应php代码include './hello.inc'
  33. 4510 getcwd("/var/www/ep"..., 4096) = 12
  34. 4510 time(NULL) = 1295425149
  35. 4510 open("/var/www/ep/hello.inc", O_RDONLY) = 4
  36. 4510 fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
  37. 4510 read(4, "\n", 8192) = 29
  38. 4510 read(4, "", 8192) = 0
  39. 4510 read(4, "", 8192) = 0
  40. 4510 close(4) = 0
  41. 4510 time(NULL) = 1295425149
  42. //-- 加载hello.inc, 对应php代码include DOCUMENT_ROOT . '/hello.inc'
  43. 4510 lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  44. 4510 lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  45. 4510 lstat64("/var/www/ep", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  46. 4510 lstat64("/var/www/ep/hello.inc", {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
  47. 4510 open("/var/www/ep/hello.inc", O_RDONLY) = 4
  48. 4510 fstat64(4, {st_mode=S_IFREG|0644, st_size=29, ...}) = 0
  49. 4510 read(4, "\n", 8192) = 29
  50. 4510 read(4, "", 8192) = 0
  51. 4510 read(4, "", 8192) = 0
  52. 4510 close(4) = 0
  53. //-- 将响结果输出给Nginx,并且关闭连接
  54. 4510 write(3, "\1\6\0\1\0V\2\0X-Powered-By: PHP/5.2.10"..., 96) = 96
  55. 4510 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
  56. 4510 write(3, "\1\3\0\1\0\10\0\0\0\0\0\0\0ere", 16) = 16
  57. 4510 shutdown(3, 1 /* send */) = 0
  58. 4510 recv(3, "\1\5\0\1\0\0\0\0", 8, 0) = 8
  59. 4510 recv(3, "", 8, 0) = 0
  60. 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查询语句。

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

其他

strace远不止这么强大,你可以善用之,我想你会离不开它的。同时,你还可以联合gdb和ltrace,你的工作会更加高效。

Linux利器 strace [看出process呼叫哪個system call]的更多相关文章

  1. Linux利器strace

    strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式 ...

  2. 使用 Linux 的 strace 命令跟踪/调试程序的常用选项

    原文:http://linoxide.com/linux-command/linux-strace-command-examples/作者: Raghu 在调试的时候,strace能帮助你追踪到一个程 ...

  3. Linux中的task,process, thread 简介

    本文的主要目的是介绍在Linux内核中,task,process, thread这3个名字之间的区别和联系.并且和WINDOWS中的相应观念进行比较.如果你已经很清楚了,那么就不用往下看了. LINU ...

  4. Linux调试分析诊断利器——strace

    strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序. 在Linux系统中,用户程 ...

  5. linux下strace命令详解

    简介 strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核 ...

  6. linux申请strace ,lstrace, ptrace, dtrace

    ltrace命令是用来跟踪进程调用库函数的情况. ltrace -hUsage: ltrace [option ...] [command [arg ...]]Trace library calls ...

  7. linux神器strace

    man strace: strace - trace system calls and signals DESCRIPTION In the simplest case strace runs the ...

  8. Finding the source of signals on Linux with strace, auditd, or systemtap

    inux and UNIX® like operating systems commonly use signals to communicate between processes. The use ...

  9. linux神器 strace解析

    除了人格以外,人最大的损失,莫过于失掉自信心了. 前言 strace可以说是神器一般的存在了,对于研究代码调用,内核级调用.系统级调用有非常重要的作用.打算了一周了,只有原文,一直没有梳理,拖延症犯了 ...

随机推荐

  1. ubuntu16.04安装docker11.09

    1.    安装Docker 操作系统 ubuntu16.04 1.1.   配置源文件 $sudo apt-get update #允许 apt 命令 HTTPS 访问 Docker 源 $sudo ...

  2. 向服务器发送post请求

    /** * 通过HttpClient发送Post请求 * @param path 请求路径 * @param params 请求参数 * @param encoding 编码 * @return 请求 ...

  3. android 短信发送

  4. 详细介绍如何计算两条折线的交点并使用Echarts展示以及图表优化

    1.背景 前段时间公司有个需求,需要在一个图表中展示两条折线,并且绘制出两条线的交点.为了满足需求大哥的需求,我也是着实想了有一会.下面我就把具体的实现过程给大家展示一下. 1.1.ECharts 简 ...

  5. AtCoder Beginner Contest 130 F Minimum Bounding Box 三分法求极值(WA)

    题意:给n个点的起始坐标以及他们的行走方向,每一单位时间每个点往它的方向移动一单位.问最小能包围所有点的矩形. 解法:看到题目求极值,想了想好像可以用三分法求极值,虽然我也不能证明面积是个单峰函数. ...

  6. 转 HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解

    HTML:scrollLeft,scrollWidth,clientWidth,offsetWidth到底指的哪到哪的距离之完全详解 scrollHeight: 获取对象的滚动高度. scrollLe ...

  7. 数据库索引原理,及MySQL索引类型(转)

    在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表: CREATE TABLE mytable( ID INT NOT NULL, username ) NOT N ...

  8. 使用conda部署jupyterhub以及ladp验证的安装

    前提:机器安装有conda环境 官方文档:http://jupyterhub.readthedocs.io/en/stable/quickstart.html 1.安装conda3 jupyterhu ...

  9. zTree节点排序、jsTree节点排序

    项目中遇到了这个问题,网上也没找到比较清晰的答案,索性提供一个方案吧. 原理:将整个树形插件的数据源进行排序,插件在构造UI时,自然也是按照顺序来排列的,目前这种思路适用于 zTree 和 jsTre ...

  10. 【leetcode】701. Insert into a Binary Search Tree

    题目如下: Given the root node of a binary search tree (BST) and a value to be inserted into the tree, in ...