百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

DTrace 和 strace 概述(traceid和spanid)

bigegpt 2024-08-03 11:40 11 浏览

使用这些惊人的工具,无需源代码或对环境的深入了解即可跟踪应用程序中的错误及其外部依赖项!


通常,在调试时,我们需要跳出 IDE 的舒适范围来重现或跟踪问题。在本系列中,我想介绍一些您可能会发现对这些情况有用的工具。我会尽量限制自己使用 100% 调试工具,而不是那些对开发测试有用的工具。

例如,curl或jq等工具非常有用。您可以/应该在调试时使用它们。但是您可能在构建和测试功能时使用了它们。因此,您应该已经熟悉它们,并且应该对它们的工作有所了解。我想专注于调试时最常使用的工具。从这个意义上说,SDKMan等工具在这里也没有任何意义。

我还想避免使用数据库工具等工具。它们在调试时非常有用,但同样,您也可能在开发过程中使用它们。它们也是非常特定于供应商的,因此这是一个广泛的主题,无法在此处涵盖。

我将在本系列中介绍的工具包括以下类别:

  • 系统监控工具:就像我们今天要讨论的 strace 和 DTrace 一样
  • 网络监视器:也属于上述范围,但需要属于自己的类别
  • VM/运行时监控:例如,让我们检查 JVM 的工具等。
  • 分析器和内存监视器

在第一篇文章中,我想讨论两个重量级冠军:DTrace 和 strace。如果您是 Java 开发人员或 Windows 用户,那么您很有可能从未听说过这些工具。您可能无意中使用了其中一个,因为在它们之上构建了如此多的工具,但情况可能并非如此。

这两种工具都可以让您在没有源代码的情况下调试任何东西。您可以发现问题并获得您从未想象过的理解水平。

DTrace


早在 2004 年,我在 Sun Microsystems 工作时第一次听说 DTrace。它在走廊里风靡一时,因为它是 Sun Microsystems 正在推广的一项创新。DTrace 后来被移植到 MacOS X(它起源于 Solaris)。今天,Windows 和 Linux 上也有端口。

DTrace 是一个强大的低级动态跟踪框架。但这只是另一个最高级,而且,如果您从未使用过这样的工具并且没有系统编程背景,您可能会感到有点困惑:它到底是做什么的?

它让你“看到”一切。想知道进程打开了哪些文件?

好的

想知道谁调用了内核 API 并获得调用者的堆栈跟踪?

好的

想知道一个进程为什么会死掉?

好的

想知道一个操作花费了多少 CPU 时间?

好的

您可能会认为 DTrace 是一种会彻底破坏您的 CPU 的工具……但这里有一个杀手级功能:它足够快,可以在生产环境中运行,而对性能影响最小甚至没有!

它在近二十年前推出时是革命性的,直到今天仍然如此!

运行 DTrace

在我们开始之前,先警告一句。保存您的数据!

这个工具很容易让你的机器崩溃。启用它需要禁用 MacOS 上的重要安全设施。这是一个有风险的“低级”系统服务,应该这样对待。

在 Mac 上,DTrace 与“系统完整性保护”冲突,后者是一种安全功能,可阻止进程之间的某些交互(除其他外)。在正常情况下,这会很棒。但是如果你想运行 DTrace,这将是一个问题。

解决方案是在 Intel Mac 上启动到恢复模式;Command-R这意味着在启动时按住键。在 ARM Mac 上,只需长按电源按钮。

然后,在恢复模式终端中,发出命令:csrutil disable.

重新启动后,DTrace 应按预期工作。

基本用法

如前所述,DTrace 是一个非常强大的工具。有整本关于它的书。它有自己的基于 C 语法的编程语言,您可以使用它来构建复杂的逻辑。例如,以下命令将从给定的回调中记录一些信息:

sudo DTrace -qn 'syscall::write:entry, syscall::sendto:entry /pid == $target/ { printf("(%d) %s %s", pid, probefunc, copyinstr(arg1)); }' -p [PID]br


传递给 DTrace 命令的代码片段侦听目标进程 ID 上的 sendto 回调。然后,它将信息打印到控制台,例如,(pid) text

如果这看起来有点太多而且太难开始......你是100%正确的。它是您需要时的强大工具。但是对于我们的大部分日常使用来说,它太强大了。我们想要的是了解一些基本的东西。

简单用法

幸运的是,我们有一个简单的解决方案:

man -k DTrace


这会打印出一个值得阅读的工具列表,只是为了了解这个东西的广泛性。以下是该命令的几行有趣的输出:

纯文本

bitesize.d(1m)           - analyse disk I/O size by process. Uses DTrace
dapptrace(1m)            - trace user and library function usage. Uses DTrace
errinfo(1m)              - print errno for syscall fails. Uses DTrace
iotop(1m)                - display top disk I/O events by process. Uses DTrace
plockstat(1)             - front-end to DTrace to print statistics about POSIX mutexes and read/write locks


值得您花时间查看此列表以了解您在这里真正可以做什么。

例子

您正面临导致应用程序性能下降的磁盘写入问题……但是是您的应用程序有问题还是其他应用程序有问题?

赶紧运行:

sudo rwbypid.d


它将打印出对磁盘的读/写:


  PID CMD                       DIR    COUNT
  2957 wordexp-helper              W        1
  2959 wc                          W        1
  2961 grep                        W        1

... snipped for clarity ...

   637 firefox                     R     6937
   637 firefox                     W    15325
   343 sentineld                   W   100287


安全软件确实降低了性能......

您还可以使用bitesize.d来获得有关写入/分配的字节数的更具体的结果。

不过这水平相当高。如果你想要细节怎么办:文件名、进程名等?


sudo iosnoop -a


打印出几乎包括您需要的所有内容的输出:

STRTIME              DEVICE  MAJ MIN   UID   PID D      BLOCK     SIZE                     PATHNAME ARGS
2022 Jun 30 12:16:56 ??        1  17   501  1111 W  150777072     4096 ??/idb/3166453069wcaw.sqlite-wal firefox\0
2022 Jun 30 12:16:56 ??        1  17   501   661 W  150777175   487424  ??/index-dir/the-real-index Slack Helper\0
2022 Jun 30 12:16:57 ??        1  17   499   342 W  150777294     4096 ??/persistent/.dat.nosync0156.ztvXap sentineld\0


我可以看到进程 ID 以及它写入特定文件的字节数!

假设您的程序跨越进程并且您想看看发生了什么。例如,我在我构建的服务器中运行源代码构建:

sudo errinfo


这让我可以检测到从系统调用返回的错误以及最初触发它的命令:

EXEC          SYSCALL  ERR  DESC
    WindowServer workq_kernreturn   -2 
    WindowServer workq_kernreturn   -2 
   SentinelAgent workq_kernreturn   -2 
   SentinelAgent workq_kernreturn   -2 
          Signal           Helper    0 
          Google           Chrome    0 
           Brave          Browser    0 
          Google           Chrome    0


这些只是冰山一角。我建议查看Oracle的这个旧的DTrace 教程或这本书。免责声明:我没有读过这本书...

strace

有趣的是,strace 工具也起源于 90 年代的 Sun Microsystems。不过,这并不奇怪,因为源自 Sun Microsystems 的技术列表绝对令人麻木。

Strace 在使用和功能上都比 DTrace 简单得多。无论好坏。由于 DTrace 需要深度操作系统支持,因此它从未成为常见 Linux 发行版的官方功能,因此,人们在 Linux 上使用 strace 而不是 DTrace。但是,它们并不完全可以互换。

strace 的启用要归功于称为 ptrace 的内核功能。由于 ptrace 已经在 Linux 中,我们不需要添加额外的内核代码或模块。通常,DTrace 需要更深入的内核支持,以解决 Linux 上的许可问题,它位于单独的可加载模块中,但这仍然存在一些挑战。

使用 strace 类似于每次我们进行内核调用时打印一个日志条目。这会为您执行的每个命令创建非常详细的日志记录。因此,您可以了解正在运行的进程背后 的真实情况。

运行 strace

现在,strace 在 Linux 中很常用。这是该平台上我最喜欢的系统诊断工具。使用它非常方便,因为我们可以在没有特殊权限的情况下运行它。请注意,与 DTrace 不同,您应该使 strace 远离生产环境(除非代码是隔离的)。它会带来巨大的性能开销,并且会导致生产系统停机。

strace 最基本的用法只是将命令行传递给它:

strace java -classpath. PrimeMain


strace 的输出很长,我们来看几行:

execve("/home/ec2-user/jdk1.8.0_45/bin/java", ["java", "-classpath.", "PrimeMain"], 0x7fffd689ec20 /* 23 vars */) = 0
brk(NULL)                               = 0xb85000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0294272000
readlink("/proc/self/exe", "/home/ec2-user/jdk1.8.0_45/bin/j"..., 4096) = 35
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/x86_64", 0x7fff37af09a0) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls", 0x7fff37af09a0) = -1 ENOENT (No such file or directory)


这些行中的每一行都是一个 Linux 系统调用。我们可以用谷歌搜索他们每个人,以了解发生了什么。这是一个简单的例子:

open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)br


Java 尝试使用系统打开调用pthread从目录中加载库以加载文件。tls系统调用的退出码是-1,表示文件不存在。在正常情况下,我们应该从这个 API 中取回一个文件描述符值。查看目录,似乎tls缺少目录。我猜这是因为缺少 JCE 安装。这可能没问题,但在某些情况下可能很有趣。

显然,有时输出量是压倒性的。我们通常只想查看“打开了哪个文件”和“我们的网络调用发生了什么”之类的内容。我们可以通过仅查看使用-e参数的特定系统调用来轻松实现这一点。

strace -e open java -classpath . PrimeMain


只会显示打开的系统调用:

open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/tls/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/tls/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/libjli.so", O_RDONLY|O_CLOEXEC) = 3
open("/home/ec2-user/jdk1.8.0_45/bin/../lib/amd64/jli/libdl.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)


您可以学习和使用许多系统调用来跟踪许多行为,例如:连接、写入等。这只是您可以使用 strace 执行的操作的冰山一角。Julia Evans 在 strace 上写了一些最详尽、最有趣的帖子。如果您想了解更多关于它的信息,可能没有比这更好的地方了(还可以查看她的其他资料……惊人的资源!)。

strace 和 Java

正如您之前看到的,strace 与 JVM 配合得很好。由于 strace 早于 Java 并且是一个非常低级的工具,因此它不了解 JVM。JVM 与大多数其他平台一样工作,并调用可用于调试其行为的系统调用。但是,由于它对某些问题的独特处理方法,某些方面可能不会像 strace 那样可见。

一个很好的例子是分配。系统工具使用 malloc,它映射到内核分配逻辑,但 Java 采用不同的路线。它管理自己的内存以提高效率并简化垃圾收集逻辑。因此,内存分配的某些方面将从 strace 输出中隐藏。这可能是因祸得福,因为有时输出可能是压倒性的。

在撰写本文时,线程与 strace 配合得很好。但未来可能并非如此,因为Loom 项目可能会改变 Java 线程和系统线程之间的一对一映射。这可能会使 strace 输出更难在重线程应用程序中查明。

最后

有各种形式的“*trace”实用程序的字母汤,它们不断地相互借鉴想法。跟上所有这些噪音是一项重大挑战。有太多很棒的工具需要介绍,不过我想在以后的文章中讨论 btrace。它与 DTrace 非常相似,但也非常特定于 JVM,因此可能值得另外发表一篇文章。

我今天讨论的工具采用不同的方法来解决类似的问题:我们如何理解二进制应用程序“真正”做了什么?安全研究人员和黑客使用这些工具来了解您的程序。他们不需要代码,也不需要反汇编来查看您实际在做什么。

您还可以使用这些工具来了解您的操作的影响。我们经常调用 API 并让事情到此结束。但魔鬼在细节中,而这些细节可能会带来沉重的代价。作为一名 Java 开发人员,我很少考虑信号传递、进程管理或其他此类低级主要内容。但我确实会花时间研究这些东西,因为它们最终会影响我的应用程序的稳定性和性能。



相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...