Linux

Linux 调试与追踪工具

·21 分钟阅读·8396 字

strace、traceroute、ltrace、perf 等 Linux 调试追踪工具的用法与输出解读

📋 目录

Linux 调试与追踪工具

1. 🌐 网络路径追踪 traceroute

1.1. 作用

探测从本机到目标 IP/域名沿途经过的路由节点 & 延迟,定位网络丢包/卡顿点。

1.2. 原理

利用 IP 头 TTL(生存时间):

  • TTL=1 → 第一跳路由超时返回 ICMP → 拿到第1跳 IP
  • TTL=2 → 第二跳超时 → 拿到第2跳 IP
  • ……直到到达目标

1.3. 常用参数


traceroute [选项] 目标IP/域名
  • -d:不解析域名(更快)
  • -f TTL:起始 TTL(默认1)
  • -m MAX_TTL:最大跳数(默认30)
  • -p PORT:指定目的端口(默认33434)
  • -q N:每跳发 N 个包(默认3)
  • -T:用 TCP 替代 UDP(穿透防火墙)

1.4. 示例


traceroute -d www.baidu.com

输出:


1  192.168.1.1  0.5ms  0.4ms  0.4ms

2  10.10.8.1    5.2ms  5.1ms  5.1ms

3  * * *          (防火墙无响应)

4  203.0.113.45 12.4ms 12.4ms 12.3ms
  • *:该跳无响应(防火墙拦截)
  • 延迟突增:链路拥塞

1.5. Windows 对应命令


tracert 目标IP

2. 🔌 ⚡ strace:跟踪进程的系统调用(排障神器)

2.1. 作用

监控进程执行的所有系统调用(open/read/write/socket/connect 等)及返回值,定位:

  • 程序启动失败(缺文件、权限不足)
  • 进程卡死(卡在某个 syscall)
  • 性能慢(频繁 syscall、IO 阻塞)

2.2. 安装


## 📌 Debian/Ubuntu

apt install strace

## 📌 CentOS/RHEL

yum install strace

2.3. 常用用法

2.3.1. 跟踪新进程


strace ls

输出:


execve("/bin/ls", ["ls"], 0x7ffd4d2e2000) = 0

brk(NULL)                               = 0x55f87a2c7000

openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3

...

2.3.2. 跟踪已运行进程(-p PID)


strace -p 1234

2.3.3. 输出到文件(-o)


strace -o trace.log -p 1234

2.3.4. 过滤特定系统调用(-e trace=)


## 💾 只看文件相关调用

strace -e trace=open,read,close cat /etc/passwd

## 🌐 只看网络调用

strace -e trace=network curl www.baidu.com

2.3.5. 跟踪子进程(-f)


strace -f ./test.sh

2.3.6. 统计耗时(-c)


strace -c ls

输出各 syscall 调用次数、耗时占比。

2.4. 关键输出字段

  • syscall(arg1, arg2...) = 返回值
  • 返回值 -1:失败,errno 显示原因(如 ENOENT 文件不存在)

3. 🔧 ltrace:跟踪库函数调用

3.1. 作用

跟踪进程调用的动态库函数(如 malloc/free/printf/strcpy),补 strace 看不到的用户态库调用。

3.2. 安装


apt install ltrace

yum install ltrace

3.3. 常用用法


## 📌 跟踪 ls 的库函数

ltrace ls

## 📌 统计调用次数

ltrace -c ls

## 🔌 同时显示系统调用

ltrace -S ls

## 📌 过滤特定函数

ltrace -e "*strcpy*" cp a.txt b.txt

4. 📌 ⚙️ ftrace:Linux 内核级跟踪(高级)

4.1. 作用

跟踪内核函数、调度、中断、系统事件,定位内核态性能问题、死锁、调度异常。

4.2. 前提:挂载 debugfs


mount -t debugfs none /sys/kernel/debug

cd /sys/kernel/debug/tracing

4.3. 核心文件

  • current_tracer:当前跟踪器(function/function_graph 等)
  • tracing_on:1=开始跟踪,0=停止
  • set_ftrace_filter:过滤要跟踪的内核函数
  • trace:跟踪结果输出

4.4. 常用示例

4.4.1. 函数调用跟踪(function)


echo function > current_tracer

echo 1 > tracing_on

## 📊 执行要监控的操作(如 ls)

echo 0 > tracing_on

cat trace

4.4.2. 函数调用图(function_graph,带耗时)


echo function_graph > current_tracer

echo __do_fault > set_graph_function  # 只跟踪缺页异常

echo 1 > tracing_on

## 📌 执行操作

echo 0 > tracing_on

cat trace

4.4.3. 跟踪系统调用


echo syscalls > current_tracer

4.5. 输出解读

  • TASK-PID CPU#:进程名-PID/CPU
  • TIMESTAMP:时间戳
  • FUNCTION:内核函数
  • DURATION:函数耗时(function_graph 模式)

5. 🚀 四种 trace 工具对比(选型)

  • traceroute:网络路由、延迟、丢包 → 网络连通性排障
  • strace:进程系统调用(文件/网络/IO)→ 应用启动失败、卡死、权限问题
  • ltrace:用户态库函数(malloc/printf)→ 内存泄漏、库调用异常
  • ftrace:内核函数/调度/中断 → 内核性能、死锁、调度问题

6. 🌐 实战场景推荐

  1. 访问文件报错:strace -e trace=open,stat 程序
  2. 接口超时/连不上:traceroute 目标IP + strace -e trace=network 程序
  3. 进程 CPU 高:strace -c 看高频 syscall;或 ftrace 看内核热点
  4. 程序崩溃:strace 看崩溃前最后调用;ltrace 看库调用;dmesg 看内核 OOM/Oops

7. 🔍 strace 输出详解

8. 📖 strace 输出字段 & 含义(重点)

9. 📖 1. 基础通用输出格式


系统调用名(参数1, 参数2, ...) = 返回值 【错误信息】

9.1. 逐段拆解示例

执行 strace ls,截取典型行:


openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3

read(3, "drwxr-xr-x  2 root root 4096 Jun  9 10:00 dir\n", 8192) = 128

futex(0x7f8b2c0009d8, FUTEX_WAIT, 2, NULL) = -1 EAGAIN (资源暂时不可用)
  • openat:系统调用名称,代表当前内核操作
  • (AT_FDCWD, ".", ...):调用入参,路径、权限、标志位等
  • = 3:返回值
  • 正数:成功,一般是文件描述符 fd
  • 0:执行成功(无返回数据)
  • -1:调用失败
  • EAGAIN:错误码,括号内是文字描述

10. 🔌 1.2 高频系统调用 + 字段解读

10.1. (1)文件类调用 open / openat / read / write / close

10.1.1. openat 示例


openat(AT_FDCWD, "/etc/hosts", O_RDONLY) = 4
  • AT_FDCWD:基于当前工作目录查找文件
  • "/etc/hosts":目标文件路径
  • O_RDONLY:只读模式;常见标识:O_WRONLY(只写)、O_RDWR(读写)、O_CREAT(创建文件)
  • = 4:成功,返回文件描述符 fd=4

10.1.2. read / write 示例


read(4, "127.0.0.1 localhost\n", 8192) = 20

write(1, "hello\n", 6) = 6
  • 第1个参数:文件描述符(1 标准输出 stdout,2 标准错误 stderr)
  • 第2个参数:读取/写入的内容
  • 第3个参数:期望读写字节数
  • 末尾数字:实际读写字节数

10.1.3. close 示例


close(4) = 0

参数=文件描述符,=0 表示关闭成功。


10.2. (2)网络类调用 socket / connect / accept / send / recv


socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 5

connect(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
  • AF_INET:IPv4 协议;SOCK_STREAM:TCP 套接字
  • =5:创建socket成功,fd=5
  • connect 参数:IP+端口结构体,=0 连接成功
  • 失败示例:connect(...) = -1 ECONNREFUSED (连接被拒绝)

10.3. (3)进程/线程类 fork / clone / execve


execve("/bin/ls", ["ls"], [/* 25 vars */]) = 0

clone(child_stack=NULL, flags=CLONE_THREAD) = 12345
  • execve:加载可执行程序,第一个参数为程序路径
  • clone:Linux 创建线程/进程的底层调用,返回子进程/线程PID

10.4. (4)锁/等待类 futex / poll / select(进程卡死高频)

10.4.1. futex 线程锁


futex(0x7fxxxx, FUTEX_WAIT, 1, NULL) = ?
  • 作用:Linux 线程互斥锁、条件等待
  • 现象:该行一直卡住不动 → 线程死锁/锁竞争,进程假死

10.4.2. poll / select IO 多路复用


poll([{fd=3, events=POLLIN}], 1, -1)
  • fd=3:监听的文件描述符
  • POLLIN:等待读事件
  • 最后 -1:无限阻塞等待(无事件则一直卡在这里)

11. ⚙️ ⚙️ 1.3 带时间戳/耗时参数的输出解读

11.1. -t 显示系统时间


10:20:30 openat(...) = 3

开头 10:20:30:系统当前时间,定位异常发生时刻。

11.2. -T 显示单次调用耗时(重点排查慢调用)


read(3, "xxx", 8192) = 128 <0.000123>

poll(...) = 1 <5.234567>
  • <0.000123>:本次系统调用耗时,单位 秒
  • 耗时秒级以上:典型慢调用、IO/网络阻塞

11.3. -c 统计汇总输出(strace -c PID)


% time     seconds  usecs/call     calls    errors syscall

------ ----------- ----------- --------- --------- ----------------

 80.00    0.500000         100      5000           read

 15.00    0.093750          15       625        10 write

  5.00    0.031250          31         1           poll

------ ----------- ----------- --------- --------- total

字段说明:

  1. % time:该系统调用耗时占总耗时百分比(占比高=性能瓶颈)
  2. seconds:累计总耗时(秒)
  3. usecs/call:单次调用平均耗时(微秒)
  4. calls:总调用次数(次数暴增=频繁系统调用,CPU高)
  5. errors:失败次数
  6. syscall:系统调用名

12. 📌 1.4 高频错误码含义(排障核心)

错误码英文描述中文含义典型场景
ENOENTNo such file or directory文件/路径不存在程序缺配置、路径写错
EACCESPermission denied权限不足读写文件、绑定特权端口
EEXISTFile exists文件已存在重复创建文件/目录
EAGAINResource temporarily unavailable资源暂时不可用非阻塞IO无数据、锁争抢
ECONNREFUSEDConnection refused连接被拒绝端口未监听、服务未启动
ETIMEDOUTConnection timed out连接超时网络不通、防火墙拦截
EINTRInterrupted system call调用被信号中断进程收到 kill 信号
ENOMEMOut of memory内存不足内存耗尽、OOM 前兆

13. 📌 ⚡ ftrace 输出字段 & 含义(内核跟踪)

前置:进入目录 cd /sys/kernel/debug/tracing,所有结果通过 cat trace 查看。

14. 🔄 2.1 公共头部字段(所有跟踪模式通用)


## 📌 tracer: function

#

## 📌 TASK-PID   CPU#      TIMESTAMP  FUNCTION

## 📌 进程名-PID  CPU编号   时间戳    内核函数名
  • TASK-PID:进程名 + 进程ID
  • CPU#:当前运行在第几颗CPU核心
  • TIMESTAMP:时间戳(单位:秒,从系统启动开始计时)
  • FUNCTION:内核函数名称

15. 🔄 2.2 模式1:function 纯函数跟踪

15.1. 示例输出


bash-1234  [001]  1234.567890: kswapd0 <- schedule

逐字段:

  1. bash-1234:进程名=bash,PID=1234
  2. [001]:运行在 CPU1
  3. 1234.567890:系统启动后经过的秒数
  4. kswapd0:当前执行的内核函数(内存回收线程)
  5. <- schedule:调用方函数(由 schedule 调度函数触发) 典型场景:
  • 大量 kswapd:内存紧张,内核频繁回收内存、使用 Swap
  • 大量 softirq 函数:软中断繁忙(网络/IO 压力大)

16. 🔄 2.3 模式2:function_graph 函数调用图(带耗时、层级,最常用)

16.1. 示例输出


 1)  nginx-5678  [000]  2345.123456:               | __do_fault() {

 2)  nginx-5678  [000]  2345.123460:               |   alloc_page() {

 3)  nginx-5678  [000]  2345.123462:   2.000 us |   }

 4)  nginx-5678  [000]  2345.123465:   9.000 us | }

字段&符号解读:

  1. 行首数字 1):CPU 编号
  2. nginx-5678:进程+PID
  3. 缩进:函数调用层级(大函数内部调用子函数)
  4. {:函数开始执行
  5. }:函数执行结束
  6. 2.000 us:函数执行耗时(微秒) 排障要点:
  • 单函数耗时几百微秒/毫秒:内核态慢函数,系统卡顿根源
  • 嵌套层级极深:内核调用链复杂,调度压力大

17. 🔌 2.4 模式3:syscalls 系统调用跟踪(内核视角)

17.1. 示例


ls-9012  [002]  3456.789000: sys_openat(filename="/etc/passwd")

ls-9012  [002]  3456.789010: sys_openat -> 3
  • sys_openat:内核层系统调用入口(对应应用层 openat)
  • filename=xxx:调用参数
  • -> 3:返回文件描述符 fd=3

18. 🔧 ltrace 输出字段 & 含义(库函数跟踪)

19. 📖 3.1 基础格式


库函数名(参数1, 参数2...) = 返回值

19.1. 示例 1:普通库调用


ls->strlen("test") = 4

ls->malloc(1024) = 0x7f1234567890
  • ls:当前进程名
  • strlen/malloc:C 标准库函数
  • 括号内:入参
  • = 4 / =0x...返回值(字符串长度 / 内存地址)

19.2. 示例 2:ltrace -c 统计输出


% time     seconds  usecs/call     calls function

------ ----------- ----------- --------- ---------

 70.00    0.200000          20     1000 strlen

 30.00    0.080000          40      200 malloc

字段和 strace -c 完全一致:耗时占比、总耗时、单次耗时、调用次数、函数名。

19.3. 典型故障

  • 大量 malloc/free 调用:频繁内存分配释放,疑似内存泄漏
  • 函数返回 NULL:库调用失败

20. 🌐 ⚙️ traceroute 输出字段 & 含义(网络路由)

21. 📖 4.1 基础输出示例


1  192.168.1.1 (192.168.1.1)  0.321 ms  0.289 ms  0.276 ms

2  10.0.0.1    5.123 ms  5.098 ms  5.101 ms

3  * * *

4  220.181.xxx.xxx 12.345 ms 12.333 ms 12.321 ms

逐列解读:

  1. 第一列(数字):路由跳数(第1跳、第2跳…)
  2. 第二部分:路由节点域名/IP
  3. 后三列:三次探测的延迟(毫秒 ms)

22. 📌 4.2 特殊符号解读

  1. * * *:该路由节点无响应
  • 原因:防火墙拦截 ICMP/TCP 探测包、路由节点禁回包
  1. 延迟突然大幅飙升:当前节点链路拥塞、带宽瓶颈
  2. 跳数过多 + 持续丢包:链路不稳定

23. ⚙️ ⚙️ 4.3 补充参数输出

  • 使用 -d:不解析域名,只显示IP,输出更简洁
  • 使用 -T:基于TCP探测,适合UDP被防火墙拦截的场景

24. 🚀 综合排障速查(现象 + 工具输出特征 + 结论)

  1. 程序启动失败strace 出现 open(...) = -1 ENOENT → 缺失文件/配置
    strace 出现 open(...) = -1 EACCES → 权限不足
  2. 进程卡死、假死strace 卡在 futex → 线程死锁
    strace 卡在 poll/select → IO/网络等待
    ftrace 某内核函数耗时极高 → 内核态阻塞
  3. CPU 占用高strace -c 某系统调用 calls 上万次 → 频繁用户态系统调用
    ftrace 大量软中断函数 → 网络/硬件中断风暴
  4. 网络连不上strace connect = -1 ECONNREFUSED → 服务未监听
    traceroute 中间跳 * * * → 链路/防火墙拦截
  5. 内存异常ftrace 大量 kswapd 函数 → 内存不足、Swap 频繁使用

关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro