找回密码
 立即注册
首页 业界区 业界 不记命令也能排障:catpaw chat 实战手册

不记命令也能排障:catpaw chat 实战手册

强怀梅 昨天 10:54
TL;DR:catpaw chat 让你用自然语言排障——说"最近有 OOM 吗",AI 帮你查 dmesg;说"谁在吃磁盘",AI 帮你跑 du 和 df。本文整理 12 个高频排障场景,每个都对比"传统命令行"和"一句话搞定",附带 AI 在幕后调用了什么工具。即使你不用 catpaw,也能当作一份排障命令速查表。
一个灵魂拷问

你能在 5 秒内回忆出以下命令吗?
  1. # 查看 TCP 各状态连接数
  2. ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
  3. # 查看某进程的线程及其 wchan(卡在哪个内核函数)
  4. ls /proc/<pid>/task | while read tid; do
  5.   echo -n "$tid "; cat /proc/$tid/wchan 2>/dev/null; echo
  6. done
  7. # 查看 conntrack 表使用率
  8. echo "$(cat /proc/sys/net/netfilter/nf_conntrack_count) / $(cat /proc/sys/net/netfilter/nf_conntrack_max)" | bc -l
  9. # 查看 Listen 队列溢出次数
  10. grep -E 'ListenOverflows|ListenDrops' /proc/net/netstat
  11. # 按磁盘 I/O 排序进程
  12. awk '{if(NR>1 && $1~/[0-9]+/) print $0}' /proc/<pid>/io
复制代码
记不住?正常。
这些命令不是用来记的——它们散落在 /proc 的几十个文件和几百个命令行工具里,每个有自己的语法和参数,组合方式千变万化。哪怕是工作十年的 SRE,排障时也经常要 Google 一下。
但现在是 2025 年了。
你有没有想过:为什么排障的时候,人类要去适应机器的语言,而不是反过来?
  1. You: 最近有 OOM 吗?
  2. AI:  发现 2 次 OOM Kill 事件……
复制代码
这就是 catpaw chat 在做的事——你说人话,它帮你跑命令。
catpaw chat 是什么

catpaw 是一个带 AI 大脑的轻量监控 Agent。catpaw chat 是它的交互排障模式:
  1. ./catpaw chat
复制代码
启动后进入对话界面,你可以用自然语言描述问题,AI 会调用内置的 90+ 诊断工具 来帮你排查,工具覆盖 CPU、内存、磁盘、网络、进程、内核、日志、容器等各个领域。
关键特性:

  • 不用记命令:说"帮我看看磁盘",AI 知道该跑什么
  • 不用解析输出:AI 看原始数据,给你总结好的结论
  • 多步推理:AI 会根据前一步结果决定下一步查什么("内存高 → 查 Top 进程 → 查具体进程的 fd 和连接")
  • 安全可控:诊断工具是只读的;如果需要执行 shell 命令,AI 会先征得你的同意
下面我们通过 12 个场景看看它怎么用。
场景 1:CPU 飙高了,谁在吃?

传统方式
  1. # 先看整体
  2. top -bn1 | head -20
  3. # 看负载是否超过核数
  4. uptime
  5. nproc
  6. # 找到 CPU 最高的进程
  7. ps aux --sort=-%cpu | head -10
  8. # 如果是 Java,还得 jstack
  9. jstack <pid> > /tmp/thread_dump.txt
复制代码
4 条命令,还得人工比对"负载 vs 核数"来判断是不是真的高。
catpaw chat
  1. You: CPU 好像有点高,帮我看看
  2. AI: [调用 cpu_usage]
  3.     当前 CPU 总使用率 87.3%,其中:
  4.     - user: 72.1%, system: 12.8%, iowait: 2.4%
  5.    
  6.     [调用 cpu_load_average]
  7.     负载 1m/5m/15m = 12.3/10.8/8.2,当前 4 核,
  8.     负载/核 比值 3.08,显著偏高。
  9.    
  10.     [调用 top_cpu_processes]
  11.     Top 3 CPU 进程:
  12.     1. java (PID 8847) — 68.2% CPU, 运行 3d12h
  13.     2. python3 (PID 12301) — 11.5% CPU, 运行 2h
  14.     3. nginx worker (PID 3021) — 3.1% CPU
  15.     结论:CPU 压力主要来自 PID 8847 的 Java 进程,持续占用
  16.     68% CPU。建议检查该进程是否存在死循环或 GC 问题。
复制代码
AI 做了什么:调用了 cpu_usage、cpu_load_average、top_cpu_processes 三个工具,自动比对"负载/核数"的比值,帮你定位到具体进程。
场景 2:最近有没有 OOM?

传统方式
  1. # 方法 1:从 dmesg 里找
  2. dmesg | grep -i "out of memory"
  3. dmesg | grep -i "oom"
  4. # 方法 2:从 journal 里找
  5. journalctl -k --since "24 hours ago" | grep -i oom
  6. # 找到了还得手动解读:被 kill 的是谁、RSS 多大、当时内存什么情况
  7. dmesg | grep -A 5 "Killed process"
复制代码
光是"怎么 grep"就有两种路径,找到了还得人工解析 OOM 日志的格式。
catpaw chat
  1. You: 最近有 OOM 吗?
  2. AI: [调用 oom_history]
  3.     发现 2 次 OOM Kill 事件:
  4.     ┌───────────────────┬─────────┬──────┬─────────┐
  5.     │ 时间               │ 进程    │  PID │ RSS     │
  6.     ├───────────────────┼─────────┼──────┼─────────┤
  7.     │ 03-14 03:12:08    │ java    │ 8847 │ 7.8 GB  │
  8.     │ 03-14 02:45:31    │ python3 │ 9123 │ 3.2 GB  │
  9.     └───────────────────┴─────────┴──────┴─────────┘
  10.    
  11.     两次事件均发生在凌晨,间隔约 30 分钟。
  12.     java 进程 RSS 达 7.8GB,可能存在内存泄漏。
  13.     建议检查 JVM heap 配置和 cgroup 内存限制。
  14. You: 看看当前的 cgroup 内存限制
  15. AI: [调用 cgroup_usage]
  16.     PID 12305 (java) 的 cgroup 内存限制:
  17.     - memory.limit: 8.0 GB
  18.     - memory.usage: 6.1 GB (76.3%)
  19.     - memory.max_usage: 7.9 GB
  20.    
  21.     进程接近 cgroup 内存上限。上次 OOM 时 RSS 7.8GB
  22.     已非常接近 8GB 限制。
复制代码
AI 做了什么:第一轮调用 oom_history(解析 dmesg 中的 OOM 事件),把原始日志整理成表格。你追问 cgroup,它又调用 cgroup_usage 查看内存限制——整个过程是多轮推理,不是一次性查完。
场景 3:磁盘空间告急

传统方式
  1. # 看哪个分区满了
  2. df -h
  3. # 找大目录
  4. du -sh /* 2>/dev/null | sort -rh | head -10
  5. du -sh /var/* 2>/dev/null | sort -rh | head -10
  6. # 看 inode(有时候文件太多 inode 先满)
  7. df -i
  8. # 查是不是有大文件被删了但进程还持有
  9. lsof +L1 | head -20
复制代码
每个 du 命令在大目录下要跑几十秒,而且你得手动一层层挖。
catpaw chat
  1. You: 磁盘快满了,帮我分析一下
  2. AI: [调用 disk_usage]
  3.     ┌────────┬───────┬──────┬──────┬────────┐
  4.     │ 挂载点 │ 总量   │ 已用 │ 可用 │ 使用率 │
  5.     ├────────┼───────┼──────┼──────┼────────┤
  6.     │ /      │ 50 GB │ 47 GB│ 3 GB │ 94.0%  │
  7.     │ /data  │ 200 GB│ 82 GB│118 GB│ 41.0%  │
  8.     └────────┴───────┴──────┴──────┴────────┘
  9.    
  10.     根分区使用率 94%,接近满。
  11.     [调用 disk_io_counters]
  12.     根分区所在设备 vda 的 I/O 正常,非性能问题。
  13.     建议我帮你查看根分区下哪些目录占用最多空间吗?
  14. You: 好,查一下
  15. AI: [调用 exec_shell: du -sh /* 2>/dev/null | sort -rh | head -10]
  16.     ⚠️ 需要执行 shell 命令:du -sh /* | sort -rh | head -10
  17.     是否允许?[Y/n]
  18. You: y
  19. AI: 根分区 Top 目录:
  20.     - /var     32.1 GB
  21.     - /usr     8.2 GB
  22.     - /home    4.3 GB
  23.     /var 最大。继续深入查看 /var 子目录:
  24.     [调用 exec_shell: du -sh /var/* 2>/dev/null | sort -rh | head -10]
  25.     - /var/log        28.7 GB
  26.     - /var/lib        2.8 GB
  27.     /var/log 占用 28.7 GB。再看具体文件:
  28.     [调用 exec_shell: ls -lhS /var/log/*.log | head -5]
  29.     - /var/log/app/access.log    25.3 GB
  30.     根因:/var/log/app/access.log 占用 25.3 GB,疑似日志未
  31.     配置轮转。建议配置 logrotate 并清理历史日志。
复制代码
注意这里的安全机制:诊断工具是只读的直接执行;du 这种 shell 命令需要你确认才执行。AI 会自动逐层深入,最终帮你定位到具体文件。
场景 4:网络不通,不知道卡在哪

传统方式
  1. # 先 ping 看通不通
  2. ping -c 3 10.0.1.5
  3. # 不通的话 traceroute 看卡在哪一跳
  4. traceroute 10.0.1.5
  5. # 域名解析有没有问题
  6. dig api.example.com
  7. nslookup api.example.com
  8. # TCP 端口通不通
  9. telnet 10.0.1.5 8080
  10. # 或者
  11. nc -zv 10.0.1.5 8080
  12. # 防火墙规则
  13. iptables -L -n
  14. # 或者新版
  15. nft list ruleset
复制代码
先 ping、再 traceroute、再查 DNS、再试端口、再看防火墙——每一步都要根据上一步的结果决定下一步做什么。这个决策链条本身就需要经验。
catpaw chat
  1. You: 我的服务连不上 10.0.1.5:8080,帮我查查
  2. AI: [调用 ping_check: host=10.0.1.5]
  3.     PING 10.0.1.5: 5 packets, 0% loss, avg RTT 1.2ms
  4.     → 网络层可达。
  5.     [调用 tcp_ping: host=10.0.1.5, port=8080]
  6.     TCP 连接 10.0.1.5:8080 失败:connection refused
  7.     → 端口未监听或被防火墙阻断。
  8.     [调用 traceroute: host=10.0.1.5]
  9.     路由正常,共 3 跳,无丢包。
  10.     结论:
  11.     - 网络层:ICMP 可达,延迟正常
  12.     - 传输层:TCP 8080 端口连接被拒绝(connection refused)
  13.     - 路由:正常
  14.    
  15.     大概率是目标机器的 8080 端口未启动服务,或本地防火墙
  16.     未放行。建议到目标机器检查服务状态和防火墙规则。
复制代码
AI 做了什么:自动按"ICMP → TCP → 路由"的顺序逐层排查,每一步根据结果决定下一步——这就是 SRE 的排查逻辑,AI 替你跑了一遍。
场景 5:CLOSE_WAIT 堆积,哪个服务在泄漏?

传统方式
  1. # 看 TCP 状态分布
  2. ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
  3. # 找 CLOSE_WAIT 对应的进程
  4. ss -tnp state close-wait
  5. # 按远端地址聚合
  6. ss -tnp state close-wait | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
  7. # 进一步查是连谁的
  8. ss -tnp state close-wait | grep <pid>
复制代码
这套 ss + awk + sort 的组合拳,没几个人能一次性敲对。
catpaw chat
  1. You: CLOSE_WAIT 好像很多,帮我看看
  2. AI: [调用 tcp_state_distribution]
  3.     TCP 连接状态分布:
  4.     - ESTABLISHED: 342
  5.     - CLOSE_WAIT:  1,847  ← 异常偏高
  6.     - TIME_WAIT:   128
  7.     - LISTEN:      23
  8.     CLOSE_WAIT 达 1847,明显异常(正常应接近 0)。
  9.     [调用 top_connections_by_port]
  10.     CLOSE_WAIT 按远端端口统计:
  11.     1. :3306 (MySQL) — 1,203 条
  12.     2. :6379 (Redis) — 589 条
  13.     3. :80 (HTTP) — 55 条
  14.     [调用 top_connections_by_local_port]
  15.     CLOSE_WAIT 按本地端口统计:
  16.     1. :8080 — 1,847 条 (来自 java, PID 8847)
  17.     结论:PID 8847 的 Java 服务累积了 1847 个 CLOSE_WAIT
  18.     连接,主要连向 MySQL(:3306) 和 Redis(:6379)。
  19.    
  20.     这是典型的连接泄漏——应用收到远端的 FIN 后未调用 close()。
  21.     建议检查数据库和 Redis 连接池的关闭逻辑。
复制代码
AI 做了什么:调用 tcp_state_distribution 看全局分布,发现 CLOSE_WAIT 异常后,用 top_connections_by_port 和 top_connections_by_local_port 从两个维度定位——哪个进程、连的谁。三个工具串联,逻辑清晰。
场景 6:进程到底在干啥?

传统方式
  1. # 基本信息
  2. ps -p <pid> -o pid,ppid,user,%cpu,%mem,etime,args
  3. # 线程
  4. ls /proc/<pid>/task | wc -l
  5. ps -T -p <pid>
  6. # 打开的文件
  7. ls -l /proc/<pid>/fd | wc -l
  8. ls -l /proc/<pid>/fd | head -20
  9. # 网络连接
  10. ss -tnp | grep "pid=<pid>"
  11. # 内存映射
  12. cat /proc/<pid>/smaps_rollup
  13. # 环境变量
  14. cat /proc/<pid>/environ | tr '\0' '\n'
复制代码
每个维度一条命令,全查一遍至少要敲六七条。
catpaw chat
  1. You: PID 8847 好像有问题,帮我全面看看
  2. AI: [调用 process_detail: pid=8847]
  3.     PID 8847 — java
  4.     ├─ User: app
  5.     ├─ Status: Running
  6.     ├─ CPU: 68.2%
  7.     ├─ RSS: 6.1 GB
  8.     ├─ Threads: 247
  9.     ├─ FDs: 4,892 / 65535 (7.5%)
  10.     ├─ Uptime: 3d 12h
  11.     └─ Cmdline: java -Xmx7g -jar /opt/app/service.jar
  12.     [调用 open_files: pid=8847]
  13.     FD 类型分布:
  14.     - socket: 3,214 (65.7%)
  15.     - regular file: 1,523 (31.1%)
  16.     - pipe: 155 (3.2%)
  17.    
  18.     socket 数量异常多,与 CLOSE_WAIT 堆积一致。
  19.     [调用 proc_threads: pid=8847]
  20.     线程状态:
  21.     - Running: 3
  22.     - Sleeping: 238
  23.     - Disk sleep: 6
  24.    
  25.     有 6 个线程处于 D 状态(不可中断睡眠),
  26.     wchan 显示卡在 io_schedule,疑似磁盘 I/O 阻塞。
  27.     综合判断:
  28.     1. CPU 68% + 247 线程 → 高负载
  29.     2. 3214 个 socket FD → 连接泄漏(CLOSE_WAIT)
  30.     3. 6 个 D 状态线程 → I/O 阻塞
  31.     建议优先修复连接泄漏,同时排查 I/O 阻塞原因。
复制代码
一句"帮我全面看看",AI 自己决定从哪几个维度切入。
场景 7:系统内核有没有异常?

传统方式
  1. # 看 dmesg(内容巨多,怎么筛选?)
  2. dmesg -T | tail -100
  3. dmesg -T | grep -iE "error|warn|fail|oom|bug|panic"
  4. # 看硬件错误
  5. dmesg -T | grep -iE "hardware|mce|edac"
  6. # 看 I/O 错误
  7. dmesg -T | grep -iE "i/o error|sector"
  8. # 看网络异常
  9. dmesg -T | grep -iE "link|carrier|nf_conntrack"
复制代码
最大的问题不是命令难记,而是 dmesg 的输出像个垃圾堆——几千行内核日志里,你需要凭经验判断哪些是信号、哪些是噪音。
catpaw chat
  1. You: 内核有没有什么异常?
  2. AI: [调用 dmesg_recent]
  3.     最近 24h 内核日志摘要:
  4.    
  5.     ⚠️ OOM (2 次)
  6.     - 03:12 Out of memory: Killed process 8847 (java), RSS 7.8GB
  7.     - 02:45 Out of memory: Killed process 9123 (python3), RSS 3.2GB
  8.    
  9.     ⚠️ I/O Error (1 次)
  10.     - 14:32 blk_update_request: I/O error, dev sdb, sector 123456
  11.    
  12.     ℹ️ Network
  13.     - nf_conntrack: table full, dropping packet (3 次)
  14.    
  15.     无 MCE/硬件错误,无 kernel panic/BUG。
  16.     重点关注:
  17.     1. 两次 OOM Kill 事件,建议检查内存配置
  18.     2. sdb 磁盘有 I/O 错误,可能是磁盘故障的前兆
  19.     3. conntrack 表满导致丢包,建议调大 nf_conntrack_max
复制代码
AI 做了什么:dmesg_recent 工具自动过滤噪音,按类别(OOM / I/O / 网络 / 硬件)分类呈现,比你手动 grep 五六次效率高得多。
场景 8:证书什么时候过期?

传统方式
  1. # 远程端点
  2. echo | openssl s_client -servername api.example.com \
  3.   -connect api.example.com:443 2>/dev/null | \
  4.   openssl x509 -noout -dates -subject -issuer
  5. # 本地证书文件
  6. openssl x509 -in /etc/ssl/certs/server.crt -noout -dates -subject
  7. # 想看完整证书链?更复杂
  8. echo | openssl s_client -showcerts -servername api.example.com \
  9.   -connect api.example.com:443 2>/dev/null
复制代码
openssl 命令的参数组合大概是 Linux 世界里最难记的东西之一。s_client 还是 x509?-noout 还是 -text?管道怎么接?每次都得搜。
catpaw chat
  1. You: 帮我看看 api.example.com 的证书什么时候过期
  2. AI: [调用 cert_inspect_remote: host=api.example.com, port=443]
  3.     TLS 证书信息:
  4.     ├─ Subject: api.example.com
  5.     ├─ Issuer: Let's Encrypt Authority X3
  6.     ├─ Not Before: 2025-01-15
  7.     ├─ Not After:  2025-04-15 (还剩 31 天)
  8.     ├─ SANs: api.example.com, *.example.com
  9.     └─ Chain: 2 certificates, valid
  10.     证书将在 31 天后过期,建议尽快续期。
  11. You: 本地的 /etc/ssl/server.crt 呢?
  12. AI: [调用 cert_inspect_file: path=/etc/ssl/server.crt]
  13.     本地证书信息:
  14.     ├─ Subject: *.internal.example.com
  15.     ├─ Not After: 2025-09-01 (还剩 170 天)
  16.     └─ Self-signed: Yes
  17.     该证书还有 170 天有效期,暂时无需处理。
复制代码
再也不用和 openssl 的参数搏斗了。
场景 9:TCP 重传严重吗?

传统方式
  1. # 从 /proc/net/snmp 读取
  2. cat /proc/net/snmp | grep Tcp
  3. # 算重传率需要采样两次做差
  4. watch -n 1 'cat /proc/net/snmp | grep Tcp'
  5. # 或者用 netstat -s
  6. netstat -s | grep -i retrans
  7. # 更细致的 TcpExt
  8. cat /proc/net/netstat | grep TcpExt
复制代码
这些计数器都是累计值,看绝对数没意义,你需要采样、算增量、除以总发送量得到比率。手工算很麻烦。
catpaw chat

[code]You: TCP 重传率高不高?AI: [调用 tcp_retrans_rate]    TCP 重传统计(采样 3 秒):    ├─ 发送段数:   12,847/s    ├─ 重传段数:   23/s    ├─ 重传率:     0.18%    ├─ 快速重传:   15/s    └─ 超时重传:   8/s    重传率 0.18%,处于正常范围(

相关推荐

您需要登录后才可以回帖 登录 | 立即注册