3.3. 记录应用程序交互
应用程序的可执行代码与操作系统和共享库的代码交互。记录这些交互的活动日志可以有足够的了解应用程序的行为,而无需调试实际的应用程序代码。另外,分析应用程序的交互可帮助识别错误清单的条件。
3.3.1. 用于记录应用程序交互的工具
Red Hat Enterprise Linux 提供多种工具来分析应用程序的交互。
- strace
strace
工具主要启用由应用程序使用的系统调用(内核功能)。-
strace
工具可以提供关于调用的详细输出,因为strace
会解释参数以及了解底层内核代码的结果。将数字转换为相应的常量名称,位组合标志扩展至标志列表,指向字符数组的指针以提供实际字符串等。可能缺少对更多最新内核功能的支持。 - 您可以过滤 traced 调用来减少捕获的数据量。
-
除了设置日志过滤器外,使用
strace
不需要任何特定的设置。 -
使用
strace
跟踪应用程序代码会导致应用程序的执行速度显著慢。因此,strace
不适用于许多生产部署。作为替代方案,请考虑使用ltrace
或 SystemTap。 -
Red Hat Developer Toolset 中提供的
strace
版本也可以执行系统调用修改。此功能可用于调试。
-
- ltrace
ltrace
工具允许将应用程序的用户空间调用记录到共享对象(动态库)。-
ltrace
工具允许对任何库进行追踪调用。 - 您可以过滤 traced 调用来减少捕获的数据量。
-
除了设置日志过滤器外,使用
ltrace
不需要任何特定的设置。 -
ltrace
工具非常轻便且快速,提供strace
的替代选择:可以跟踪库中相应的接口,如glibc
,使用ltrace
而不是使用strace
跟踪内核功能。 -
因为
ltrace
不会象strace
一样处理一组已知的调用,所以不会试图解释传递给库函数的值。ltrace
输出仅包含原始数字和指针。ltrace
输出的解释需要咨询输出中存在库的实际接口声明。
注意在 Red Hat Enterprise Linux 9 中,一个已知问题会阻止
ltrace
追踪系统可执行文件。这个限制不适用于用户提供的可执行文件。-
- SystemTap
SystemTap 是一个检测平台,用于探测在 Linux 系统上运行的进程和内核活动。SystemTap 使用自己的脚本语言来编程自定义事件处理程序。
-
与使用
strace
和ltrace
进行比较,使用脚本进行日志处理意味着在初始设置阶段有更多工作。但是,脚本功能除生成日志外,扩展 SystemTap 的有用性。 - SystemTap 通过创建和插入内核模块来工作。SystemTap 的使用效率更高,且不会自行创建系统或应用程序的执行速度。
- SystemTap 附带一组用法示例。
-
与使用
- GDB
GNU Debugger(GDB)主要用于调试,而不是处理日志记录。但是,它的某些功能在应用程序交互是值得关注的主要活动的情况中发挥用处。
- 使用 GDB,可以方便地将交互事件的捕获与后续执行路径的立即调试。
- 在其他工具的初始识别问题后,GDBDB 最适合分析响应不常或分散事件。在任何带有频繁事件的情况中使用 GDB 变得效率不低甚至不可能。
3.3.2. 使用 strace 监控应用程序的系统调用
strace
工具启用监控应用程序执行的系统(内核)调用。
先决条件
-
必须在系统中安装了
strace
。
步骤
- 识别要监控的系统调用。
启动
strace
并将其附加到程序。如果要监控的程序没有运行,请启动
strace
并指定 program :$ strace -fvttTyy -s 256 -e trace=call program
如果程序已在运行,找到其进程 ID(pid)并将
strace
附加到它:$ ps -C program (...) $ strace -fvttTyy -s 256 -e trace=call -ppid
-
使用要显示的系统调用替换 call。您可以多次使用
-e trace=call
选项。如果没有使用,strace
将显示所有系统调用类型。如需更多信息,请参阅 strace(1) 手册页。 -
如果您不想跟踪任何 fork 进程或线程,请退出
-f
选项。
strace
工具显示由应用发出的系统调用及其详情。在大多数情况下,应用程序及其库会立即出现大量调用和
strace
输出,如果没有设置系统调用的过滤器。当程序退出时,
strace
工具会退出。要在 traced 程序退出前终止监控,请按
。-
如果
strace
启动程序,则程序会与strace
一起终止。 -
如果您将
strace
附加到已在运行的程序中,则程序会与strace
一起终止。
-
如果
分析应用所完成的系统调用列表。
- 当调用返回错误时,日志中会出现资源访问或可用性的问题。
- 传递给系统调用和调用序列模式的值可以了解应用程序的行为。
- 如果应用程序崩溃,重要信息可能会在日志的末尾。
- 输出中包含大量不必要的信息。但是,您可以为感兴趣的系统调用构建更加精确的过滤器,并重复这个过程。
最好查看输出并将其保存到文件中。使用 tee
命令实现这一目的:
$ strace ... |& tee your_log_file.log
其他资源
strace(1) 手册页:
$ man strace
- 如何使用 strace 来跟踪命令发出的系统调用? - 知识库文章
- Red Hat Developer Toolset 用户指南 - strace 章
3.3.3. 使用 ltrace 监控应用程序的库功能调用
ltrace
工具可监控应用程序对库中可用函数的调用(共享对象)。
在 Red Hat Enterprise Linux 9 中,一个已知问题会阻止 ltrace
追踪系统可执行文件。这个限制不适用于用户提供的可执行文件。
先决条件
-
在系统中必须安装
ltrace
。
步骤
- 如果可能,请确定感兴趣的库和功能。
启动
ltrace
并将其附加到程序。如果要监控的程序没有运行,请启动
ltrace
并指定 program :$ ltrace -f -l library -e function program
如果程序已在运行,找到其进程 ID(pid)并为其附加
ltrace
:$ ps -C program (...) $ ltrace -f -l library -e function -ppid program
使用
-e
、-f
和-l
选项过滤输出:-
提供要显示的函数名称作为 function。
-e function
选项可以多次使用。如果省略,ltrace
会显示对所有功能的调用。 -
您可以使用
-l library
选项指定整个库,而不是指定功能。这个选项的行为与-e function
选项类似。 -
如果您不想跟踪任何 fork 进程或线程,请退出
-f
选项。
如需更多信息,请参阅 ltrace(1)_ manual page。
-
提供要显示的函数名称作为 function。
ltrace
显示应用程序发出的库调用。在大多数情况下,如果没有设置任何过滤器,应用程序会立即显示大量调用和
ltrace
输出。当程序退出时,
ltrace
会退出。要在 traced 程序退出前终止监控,请按
。-
如果
ltrace
启动程序,则程序会与ltrace
一起终止。 -
如果您将
ltrace
附加到已运行程序,则程序会与ltrace
一起终止。
-
如果
分析应用所完成的库调用列表。
- 如果应用程序崩溃,重要信息可能会在日志的末尾。
- 输出中包含大量不必要的信息。但是,您可以构建更加精确的过滤器并重复这个过程。
最好查看输出并将其保存到文件中。使用 tee
命令实现这一目的:
$ ltrace ... |& tee your_log_file.log
其他资源
ltrace(1) 手册页:
$ man ltrace
- Red Hat Developer Toolset User Guide - ltrace
3.3.4. 使用 SystemTap 监控应用程序的系统调用
SystemTap 工具为内核事件注册自定义事件处理程序。与 strace
工具相比,使用它较复杂,但它的效率更高,并可以启用更复杂的处理逻辑。名为 strace.stp
的 SystemTap 脚本与 SystemTap 一起安装,并可实现使用 SystemTap 的 strace
大致相同的功能。
先决条件
- 必须在系统中安装 SystemTap 和相关的内核软件包。
步骤
找到您要监控的进程 ID(pid):
$ ps -aux
使用
strace.stp
脚本运行 SystemTap:# stap /usr/share/systemtap/examples/process/strace.stp -x pid
pid 的值是进程 ID。
脚本编译到内核模块中,然后载入该模块。这会在输入命令并获取输出之间引入小延迟。
- 当进程执行系统调用时,调用名称及其参数会打印到终端中。
-
当进程终止或按
Ctrl+C
时,该脚本会退出。
3.3.5. 使用 GDB 截获应用程序系统调用
GNU Debugger(GDB)可让您在程序执行过程中的不同情况下停止执行。要在程序执行系统调用时停止执行,请使用 GDB 捕获点。
先决条件
- 您必须了解 GDB 断点的使用。
- GDB 必须附加到程序。
步骤
设置 catchpoint:
(gdb) catch syscall syscall-name
命令
catch syscall
设置了一个特殊的断点,它会在程序执行系统调用时停止执行。syscall-name
选项指定调用的名称。您可以为各种系统调用指定多个追踪点。使用syscall-name
选项会使 GDB 在任意系统调用中停止。开始执行程序。
如果程序还没有启动执行,请启动它:
(gdb) r
如果程序执行停止,请恢复它:
(gdb) c
- GDB 在程序执行任何指定的系统调用后停止执行。
其他资源
- 使用 GDB 调试 - 设置 Watchpoints
3.3.6. 使用 GDB 截获应用程序处理信号
GNU Debugger(GDB)可让您在程序执行过程中的不同情况下停止执行。要在程序收到操作系统信号时停止执行,请使用 GDB 捕获点。
先决条件
- 您必须了解 GDB 断点的使用。
- GDB 必须附加到程序。
步骤
设置 catchpoint:
(gdb) catch signal signal-type
命令
catch signal
设定一种特殊类型的断点,它会在程序收到信号时停止执行。signal-type
选项指定信号的类型。使用特殊值"all"
捕获所有信号。让程序运行。
如果程序还没有启动执行,请启动它:
(gdb) r
如果程序执行停止,请恢复它:
(gdb) c
- GDB 在程序收到任何指定信号后停止执行。
其他资源
- 使用 GDB 调试 — 5.1.3 Setting Catchpoints