strace 可以解决什么问题？
这些解决的问题都是关于寻找程序依赖的文件、找出程序卡住或慢的原因、或者找出程序失败的原因。
strace
这些解决的问题都是关于寻找程序依赖的文件、找出程序卡住或慢的原因、或者找出程序失败的原因。
![](/data/attachment/album/202104/05/094825y66126r56z361rz1.jpg)


昨天我 [在 Twitter 上询问大家用 strace 解决了什么问题？](https://twitter.com/b0rk/status/1378014888405168132)，和往常一样，大家真的是给出了自己的答案! 我收到了大约 200 个答案，然后花了很多时间手动将它们归为 9 类。


这些解决的问题都是关于寻找程序依赖的文件、找出程序卡住或慢的原因、或者找出程序失败的原因。这些总体上与我自己使用 `strace` 的内容相吻合，但也有一些我没有想到的东西!


我不打算在这篇文章里解释什么是 `strace`，但我有一本 [关于它的免费杂志](https://wizardzines.com/zines/strace) 和 [一个讲座](https://www.youtube.com/watch?v=4pEHfGKB-OE) 以及 [很多博文](https://jvns.ca/categories/strace)。


### 问题 1：配置文件在哪里？


最受欢迎的问题是“这个程序有一个配置文件，但我不知道它在哪里”。这可能也是我最常使用 `strace` 解决的问题，因为这是个很简单的问题。


这很好，因为一个程序有一百万种方法来记录它的配置文件在哪里（在手册页、网站上、`--help`等），但只有一种方法可以让它真正打开它（用系统调用！）。


### 问题 2：这个程序还依赖什么文件？


你也可以使用 `strace` 来查找程序依赖的其他类型的文件，比如：


* 动态链接库（“为什么我的程序加载了这个错误版本的 `.so` 文件？"），比如 [我在 2014 年调试的这个 ruby 问题](https://jvns.ca/blog/2014/03/10/debugging-shared-library-problems-with-strace/)
* 它在哪里寻找它的 Ruby gem（Ruby 出现了几次这种情况！）
* SSL 根证书
* 游戏的存档文件
* 一个闭源程序的数据文件
* [哪些 node\_modules 文件没有被使用](https://indexandmain.com/post/shrink-node-modules-with-refining)


### 问题 3：为什么这个程序会挂掉？


你有一个程序，它只是坐在那里什么都不做，这是怎么回事？这个问题特别容易回答，因为很多时候你只需要运行 `strace -p PID`，看看当前运行的是什么系统调用。你甚至不需要看几百行的输出。


答案通常是“正在等待某种 I/O”。“为什么会卡住”的一些可能的答案（虽然还有很多！）：


* 它一直在轮询 `select()`
* 正在 `wait()` 等待一个子进程完成
* 它在向某个没有响应的东西发出网络请求
* 正在进行 `write()`，但由于缓冲区已满而被阻止。
* 它在 stdin 上做 `read()`，等待输入。


有人还举了一个很好的例子，用 `strace` 调试一个卡住的 `df` 命令：“用 `strace df -h` 你可以找到卡住的挂载，然后卸载它”。


### 问题 4：这个程序卡住了吗？


这是上一个问题的变种：有时一个程序运行的时间比你预期的要长，你只是想知道它是否卡住了，或者它是否还在继续进行。


只要程序在运行过程中进行系统调用，用 `strace` 就可以超简单地回答这个问题：只需 `strace` 它，看看它是否在进行新的系统调用!


### 问题 5：为什么这个程序很慢？


你可以使用 `strace` 作为一种粗略的剖析工具：`strace -t` 会显示每次系统调用的时间戳，这样你就可以寻找大的漏洞，找到罪魁祸首。


以下是 Twitter 上 9 个人使用 `strace` 调试“为什么这个程序很慢？”的小故事。


* 早在 2000 年，我帮助支持的一个基于 Java 的网站在适度的负载下奄奄一息：页面加载缓慢，甚至完全加载不出来。我们对 J2EE 应用服务器进行了测试，发现它每次只读取一个类文件。开发人员没有使用 BufferedReader，这是典型的 Java 错误。
* 优化应用程序的启动时间……运行 `strace` 可以让人大开眼界，因为有大量不必要的文件系统交互在进行（例如，在同一个配置文件上反复打开/读取/关闭；在一个缓慢的 NFS 挂载上加载大量的字体文件，等等）。
* 问自己为什么在 PHP 中从会话文件中读取（通常是小于 100 字节）非常慢。结果发现一些 `flock` 系统调用花了大约 60 秒。
* 一个程序表现得异常缓慢。使用 `strace` 找出它在每次请求时，通过从 `/dev/random` 读取数据并耗尽熵来重新初始化其内部伪随机数发生器。
* 我记得最近一件事是连接到一个任务处理程序，看到它有多少网络调用（这是意想不到的）。
* `strace` 显示它打开/读取同一个配置文件数千次。
* 服务器随机使用 100% 的 CPU 时间，实际流量很低。原来是碰到打开文件数限制，接受一个套接字时，得到 EMFILE 错误而没有报告，然后一直重试。
* 一个工作流运行超慢，但是没有日志，结果它做一个 POST 请求花了 30 秒而超时，然后重试了 5 次……结果后台服务不堪重负，但是也没有可视性。
* 使用 `strace` 注意到 `gethostbyname()` 需要很长时间才能返回（你不能直接看到 `gethostbyname`，但你可以看到 `strace` 中的 DNS 数据包）


### 问题 6：隐藏的权限错误


有时候程序因为一个神秘的原因而失败，但问题只是有一些它没有权限打开的文件。在理想的世界里，程序会报告这些错误（“Error opening file /dev/whatever: permission denied”），当然这个世界并不完美，所以 `strace` 真的可以帮助解决这个问题!


这其实是我最近使用 `strace` 做的事情。我使用了一台 AxiDraw 绘图仪，当我试图启动它时，它打印出了一个难以理解的错误信息。我 `strace` 它，结果发现我的用户没有权限打开 USB 设备。


### 问题 7：正在使用什么命令行参数？


有时候，一个脚本正在运行另一个程序，你想知道它传递的是什么命令行标志！


几个来自 Twitter 的例子。


* 找出实际上是用来编译代码的编译器标志
* 由于命令行太长，命令失败了


### 问题 8：为什么这个网络连接失败？


基本上，这里的目标是找到网络连接的域名 / IP 地址。你可以通过 DNS 请求来查找域名，或者通过 `connect` 系统调用来查找 IP。


一般来说，当 `tcpdump` 因为某些原因不能使用或者只是因为比较熟悉 `strace` 时，就经常会使用 `strace` 调试网络问题。


### 问题 9：为什么这个程序以一种方式运行时成功，以另一种方式运行时失败？


例如：


* 同样的二进制程序在一台机器上可以运行，在另一台机器上却失败了
* 可以运行，但被 systemd 单元文件生成时失败
* 可以运行，但以 `su - user /some/script` 的方式运行时失败
* 可以运行，作为 cron 作业运行时失败


能够比较两种情况下的 `strace` 输出是非常有用的。虽然我在调试“以我的用户身份工作，而在同一台计算机上以不同方式运行时却失败了”时，第一步是“看看我的环境变量”。


### 我在做什么：慢慢地建立一些挑战


我之所以会想到这个问题，是因为我一直在慢慢地进行一些挑战，以帮助人们练习使用 `strace` 和其他命令行工具。我的想法是，给你一个问题，一个终端，你可以自由地以任何方式解决它。


所以我的目标是用它来建立一些你可以用 `strace` 解决的练习题，这些练习题反映了人们在现实生活中实际使用它解决的问题。


### 就是这样!


可能还有更多的问题可以用 `strace` 解决，我在这里还没有讲到，我很乐意听到我错过了什么!


我真的很喜欢看到很多相同的用法一次又一次地出现：至少有 20 个不同的人回答说他们使用 `strace` 来查找配置文件。而且和以往一样，我觉得这样一个简单的工具（“跟踪系统调用！”）可以用来解决这么多不同类型的问题，真的很令人高兴。




---


via: <https://jvns.ca/blog/2021/04/03/what-problems-do-people-solve-with-strace/>


作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

