20.3. 记录应用程序互动


应用程序的可执行代码与操作系统和共享库的代码交互。记录这些交互的活动日志可在不调试实际应用程序代码的情况下充分洞察应用的行为。另外,分析应用程序的交互可帮助确定存在错误清单的条件。

20.3.1. 记录应用程序交互的有用工具

红帽企业 Linux 提供用于分析应用程序的交互的多种工具。

strace

strace 工具可跟踪(和修改)应用程序与 Linux 内核之间的交互:系统调用、信号发送和进程状态更改。

  • strace 输出的详细内容,并说明调用良好,因为 strace 解释底层内核代码的参数和结果。将数字转换为对应的常数名称、对标记列表扩展的位明组合标志,指向字符数组的指针以提供实际字符串,等等。但是,对最新内核功能的支持可能会缺乏。
  • 使用 strace 不需要任何特定设置,除了设置日志过滤器外。
  • 使用 strace 跟踪应用代码可能会导致应用程序的执行速度显著下降。因此,strace 不适用于很多生产部署。作为替代方案,在这样的情形中使用 SystemTap。
  • 您可以限制 traced 系统调用和信号列表,以减少捕获的数据量。
  • strace 仅捕获内核用户空间交互,而不 trace 库调用,例如:考虑对追踪库调用使用 ltrace。
ltrace

ltrace 工具支持将应用的用户空间调用记录到共享对象(动态库)。

  • ltrace 可启用对任何库的追踪调用。
  • 您可以过滤跟踪的调用来减少捕获的数据量。
  • 使用 ltrace 不需要任何特定设置,除了设置日志过滤器外。
  • ltrace 是轻量级而快速的,为 strace 提供替代 strace 的替代方案:可以使用 ltrace 追踪库 中的对应 接口,而不是通过 strace 跟踪内核功能。但请注意,l trace 在 syscall 跟踪时可能不太精确。
  • ltrace 能够对有限库调用集进行解码参数:相关配置文件中定义了原型的调用。作为 ltrace 软件包的一部分,提供了一些 libacllibclibm 调用和系统调用的原型。ltrace 输出主要仅包含原始数字和指针。ltrace 输出的解释通常需要咨询输出中存在的库的实际接口声明。
SystemTap

SystemTap 是一个检测平台,用于在 Linux 系统上探测运行中的进程和内核活动。SystemTap 使用自己的脚本语言来编程自定义事件处理程序。

  • 与使用 straceltrace 相比,编写日志意味着在初始设置阶段有更多工作。但是,该脚本功能将 SystemTap 的用处扩展至生成日志之外。
  • SystemTap 通过创建和插入内核模块来工作。SystemTap 的使用效率更高,不会自行造成系统或应用执行的显著下降。
  • SystemTap 附带了一组使用示例。
GDB

GNU Debugger 主要用于调试,而不是日志记录。但是,其某些功能即使在应用程序交互是关注的主要活动的情况下也使其有用。

  • 借助 GDB,可以将交互事件的捕获和后续执行路径的即时调试轻松结合在一起。
  • 在其他工具的初始识别问题后,GDB 最适合分析对非经常性或具体事件的响应。在任何有频繁事件的情况下使用 GDB 都会变得效率低下甚至不可能。
其它资源

20.3.2. 通过 strace 监控应用程序的系统调用

strace 工具可跟踪(和可选修改)与 Linux 内核之间的交互:系统调用、信号发送和进程状态更改。

先决条件
  • strace 安装在系统中

    • 要安装 strace,以 root 用户身份运行:

      # yum install strace
步骤

请注意,strace 的追踪规格语法提供正则表达式和 syscall 类,以帮助识别系统调用。

  1. 运行 或附加到您想要监控的进程。

    • 如果您要监控的程序没有运行,请启动 追踪 并指定 程序

      $ strace -fvttTyy -s 256 -e trace=call program

      上述示例中使用的选项不是强制性的。在需要时使用:

      • f 选项是 "跟进分叉"的缩写。这个选项跟踪由 fork、vfork 和克隆系统调用创建的子项。
      • v 或 -e abbrev=none 选项可禁用输出的缩写,省略了各种结构字段。
      • tt 选项是 - t 选项的一个变体,使用绝对时间戳为每一行加上前缀。通过 -tt 选项,打印的时间包括 microseconds。
      • t 选项打印行末尾的每个系统调用所花费的时间长度。
      • yy 选项是 -y 选项的一个变体,它可以打印与文件描述符编号关联的路径。yy 选项不仅打印路径,还打印与套接字文件描述符和设备描述符关联的协议特定信息,或者与设备文件描述符关联的字符设备编号。
      • s 选项控制 要打印的最大字符串大小。请注意,文件名不被视为字符串,并且始终全部打印。
      • -e trace 控制追踪的系统调用集合。

        使用要显示的系统调用列表替换 call如果缺少 调用,strace 将显示所有系统调用。strace(1) 手册页中提供了部分系统调用的 Shorthands。

    • 如果程序已在运行,找到其进程 ID(pid),并为它附加 strace

      $ ps -C program
      (...)
      $ strace -fvttTyy -s 256 -e trace=call -ppid
    • 如果您不想跟踪任何已分叉的进程或线程,请不要使用 -f 选项。
  1. strace 显示由应用发出的系统调用及其详细信息。

    在大多数情况下,如果未设置系统调用过滤器,应用及其库都会立即发出大量调用和 strace 输出。

  2. 当所有 traced 进程退出时,strace 会退出。要在跟踪程序退出前终止监控,请按 Ctrl+C

    • 如果 strace 启动 程序,它将向正在启动的程序发送终止信号(SIGINT)。但请注意,该程序依次可能忽略该信号。
    • 如果您 将 trace 附加到 已在运行的程序,程序会一起终止
  3. 分析应用执行的系统调用列表。

    • 当调用返回错误时,日志中会出现与资源访问或可用性相关的问题。
    • 传递给系统调用和调用序列模式的值可让您了解应用程序的原因。
    • 如果应用程序崩溃,重要信息可能是在日志的末尾。
    • 输出中包含大量额外的信息。但是,您可以构建一个更精确的过滤器并重复该过程。
备注
  • 益处是查看输出并将其保存到文件中。要做到这一点,请运行 tee 命令:

    $ strace ...-o |tee your_log_file.log>&2
  • 要查看与不同进程对应的独立输出,请运行:

    $ strace ... -ff -o your_log_file

    带有进程 ID 的进程的输出(pid)将保存在 your_log_file.pid 中。

其它资源

20.3.3. 通过 ltrace 监控应用程序的库函数调用

ltrace 工具支持对应用所进行的调用的监控到库中可用的功能(共享对象)。

先决条件
步骤
  1. 识别感兴趣的库和功能(如果可能)。
  2. 如果您要监控的程序没有运行,请启动 ltrace 并指定 程序

    $ ltrace -f -l library -e function program

    使用 -e-l 选项过滤输出:

    • 请提供函数名称,使其显示为 函数e 函数 选项可多次使用。如果左侧,l trace 将显示所有功能的调用。
    • 您可以使用 -l 选项指定整个库,而不是指定函数。这个选项的行为与 -e 函数 选项类似。

    如需更多信息,请参阅 ltrace(1)_ 手册页。

    如果程序已在运行,请查找其进程 ID(pid)并附加 ltrace 到其中:

    $ ps -C program
    (...)
    $ ltrace ... -ppid

    如果您不想跟踪任何已分叉的进程或线程,请离开 -f 选项。

  3. ltrace 显示应用发出的库调用。

    在大多数情况下,如果没有设置过滤器,应用程序将产生大量调用,如果未设置过滤器,则立即出现 ltrace 输出。

  4. 当程序 退出时,ltrace 会退出。

    要在 traced 程序退出前终止监控,请按 enter ctrl+C

    • 如果 ltrace 启动了程序,程序会一起使用 ltrace 终止。
    • 如果您将 ltrace 附加到已在运行的程序,程序会一起终止 ltrace
  5. 分析应用执行的库调用列表。

    • 如果应用程序崩溃,重要信息可能是在日志的末尾。
    • 输出中包含大量不必要的信息。但是,您可以构建一个更精确的过滤器并重复该过程。
注意

益处是查看输出并将其保存到文件中。使用 tee 命令实现这一点:

$ ltrace ... |& tee your_log_file.log
其它资源
  • strace(1) 手册页
  • Red Hat Developer Toolset User Guide - ltrace

20.3.4. 使用 SystemTap 监控应用程序的系统调用

SystemTap 工具支持为内核事件注册自定义事件处理程序。与 strace 相比,使用起来更难于使用,但 SystemTap 效率更高,并启用更复杂的处理逻辑。

先决条件
步骤
  1. 使用以下内容创建 my_script.stp 文件:

    probe begin
    {
      printf("waiting for syscalls of process %d \n", target())
    }
    
    probe syscall.*
    {
      if (pid() == target())
        printf("%s(%s)\n", name, argstr)
    }
    
    probe process.end
    {
      if (pid() == target())
        exit()
    }
  2. 查找您要监控的进程的进程 ID(pid):

    $ ps -aux
  3. 使用脚本运行 SystemTap

    # stap my_script.stp -x pid

    pid 的值是进程 ID。

    脚本编译到之后载入的内核模块。这在输入命令和获取输出之间引入了一些延迟。

  4. 当进程执行系统调用时,调用名称及其参数将打印到终端。
  5. 当进程终止或按 Ctrl+C 时,脚本将退出。
其它资源
  • SystemTap 入门指南
  • SystemTap Tapset 参考
  • 一个大型 SystemTap 脚本(约roximates strace 功能)作为 /usr/share/systemtap/examples/process/strace.stp 可用。要运行脚本:

    # stap --example strace.stp -x pid

    # stap --example strace.stp -c "cmd args …​"

20.3.5. 使用 GDB 互动应用程序系统调用

GDB 启用在执行程序的过程中停止各种情况的执行。要在程序执行系统调用时停止执行,请使用 GDB 捕获点

先决条件

使用 GDB 在系统调用时停止程序执行

  1. 设置捕获点:

    (gdb) catch syscall syscall-name

    命令 catch syscall 设置一个特殊类型的断点,在程序执行系统调用时停止执行。

    syscall-name 选项指定调用的名称。您可以为各种系统调用指定多个捕获点。退出 syscall-name 选项会导致 GDB 在任何系统调用时停止。

  2. 如果程序还没有开始执行,请启动它:

    (gdb) r

    如果程序执行只停止,请恢复它:

    (gdb) c
  3. GDB 在程序执行任何指定系统调用后停止执行。
其它资源

20.3.6. 使用 GDB 通过应用程序中断信号

GDB 启用在执行程序的过程中停止各种情况的执行。要在程序收到操作系统信号时停止执行,请使用 GDB 捕获点

先决条件
使用 GDB 停止接收信号的程序执行
  1. 设置捕获点:

    (gdb) catch signal signal-type

    命令 catch signal 会设置一个特殊类型的断点,从而在收到程序收到信号时停止执行。signal-type 选项指定信号的类型。使用特殊值 "all" 来捕获所有信号。

  2. 如果程序还没有开始执行,请启动它:

    (gdb) r

    如果程序执行只停止,请恢复它:

    (gdb) c
  3. GDB 会在程序收到任何指定的信号后停止执行。
其它资源
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.