witr 使用指南:从“什么在运行”到“为什么在运行”
一、介绍
witr 是一个用 Go 编写的系统诊断工具,名称来自它要回答的核心问题:“Why is this running?”(这为什么在运行?)。
传统的 ps、top、lsof、ss 告诉你的是一堆“事实”——哪个进程在跑、哪个端口被占。witr 做的事不一样:它把这些事实串成一条因果链。你给它一个 PID、端口或容器名,它往上追溯:是谁启动了它?是 systemd 服务、Docker Compose、npm dev server,还是某个 SSH 会话?
它的定位是“在经典可观测性命令之上的一层因果解释”,尤其适合开发者在本地机器、容器、服务管理器和语言特定的开发服务器之间来回切换时使用。
github地址:https://github.com/pranshuparmar/witr
二、安装
witr 的安装方式覆盖了几乎所有主流平台和包管理器。以下按平台分类。
Windows
# Winget(推荐)
winget install -e --id PranshuParmar.witr
# Scoop
scoop install main/witr
# Chocolatey
choco install witr
# 一行式 PowerShell 脚本
irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex
Windows 版本使用 Get-CimInstance、tasklist、netstat 收集信息,不需要 WSL 或 PowerShell 兼容层。
macOS / Linux
# Homebrew(macOS 和 Linux)
brew install witr
# 通用一行式脚本
curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bash
# Conda(跨平台)
conda install -c conda-forge witr
# Arch Linux (AUR)
yay -S witr-bin
# Go 直接安装
go install github.com/pranshuparmar/witr/cmd/witr@latest
此外还提供 .deb / .rpm / .apk 原生包,以及 Nix、npm、FreeBSD Ports、GNU Guix 等多种渠道。
安装后验证:witr --version,查看手册:man witr。
三、核心使用场景与命令
3.1 按端口排查:谁占了我的 8080?
witr --port 8080
# 或简写
witr -p 8080
输出不仅告诉你 PID,还会显示因果链——比如 node → npm → zsh → terminal,让你一眼看到这个开发服务器是怎么被拉起来的。
3.2 按 PID 或进程名追溯来源
# 按 PID
witr 1234
# 按名称(默认子串模糊匹配)
witr nginx
# 精确匹配
witr nginx --exact
# 或
witr nginx -x
如果输入的名称匹配到多个进程,witr 会列出所有候选项并要求你指定具体 PID,避免误判。
3.3 组合查询:一条命令回答多个问题
witr 的目标参数可以混合、重复使用,结果按输入顺序依次输出,用带标签的分隔线划分区块:
witr nginx --port 5432 --pid 1234
输出会分成三个清晰的区块:
----- [name: nginx] -----
----- [port: 5432] -----
----- [pid: 1234] -----
这让“同时查多个不相关的对象”变成一条命令的事。
3.4 交互式 TUI 仪表盘
witr --interactive
# 或
witr -i
启动一个终端仪表盘,分标签页展示进程、端口、容器和文件锁。快捷键包括:
| 按键 | 功能 |
|---|---|
↑ / ↓ | 导航进程列表 |
Enter | 展开因果链详情 |
f | 过滤/搜索 |
r | 刷新 |
q / Ctrl+C | 退出 |
四、进阶用法
4.1 JSON 输出:接入自动化
witr --json 1234
witr --json --port 8080
适合脚本解析,例如在 Shell 脚本里判断端口归属:
if witr --json --port 8080 > /tmp/w.json 2>/dev/null; then
SERVICE=$(jq -r '.causality_chain[-1].service // "unknown"' /tmp/w.json)
echo "8080 归属:$SERVICE"
fi
4.2 监视模式
witr --watch 1234
持续刷新,观察进程状态变化,适合调试启动过程中的竞态问题。
4.3 按用户过滤
witr --all --user www-data
查看特定用户拥有的所有进程及其来源。
五、平台支持与限制
witr 在四大平台上都有支持,但功能完整度有差异:
| 功能 | Linux | macOS | Windows | FreeBSD |
|---|---|---|---|---|
| 按端口查询 | ✅ | ✅ | ✅ | ✅ |
| 服务管理器检测 | systemd | launchd | Windows Services | rc.d |
| 容器检测 | ✅ | ✅ | ✅ | ✅ |
| 环境变量 | ✅ | ⚠️ 部分 | ❌ | ✅ |
| 按文件查询 | ✅ | ✅ | ❌ | ✅ |
| 计划任务检测 | ✅ | ✅ | ❌ | ❌ |
Windows 上不支持的功能:按文件句柄查询、环境变量查看、tmux/screen 检测、计划任务检测。容器和 Git 仓库检测是支持的。
六、优化与技巧
6.1 权限问题
在 Linux/FreeBSD 上,witr 需要读取 /proc 等系统目录。如果看不到预期信息,加 sudo:
sudo witr --port 80
macOS 上部分操作也可能需要提升权限。
6.2 与现有工具链配合
witr 不是要替代 ps、lsof,而是补充它们。典型工作流是:用 ss 或 netstat 发现异常端口 → 用 witr --port 追溯来源 → 用 witr --watch 观察后续变化。
6.3 容器场景
witr 能识别 Docker、Podman、K8s(Kubepods)、Containerd,以及 macOS/Linux 上的 Colima。对 Docker Compose 项目,它会显示 Compose 映射信息。
witr <容器内进程的PID>
# 输出会显示:container → container runtime → systemd 链
6.4 在脚本中使用
由于 --json 输出结构稳定,witr 很适合嵌入运维脚本。结合 jq 可以提取因果链中的服务名、父进程等信息,用于自动化告警或审计。
6.5 多目标查询的输出定位
当一条命令查询多个目标时,输出按输入顺序排列,每个区块前有 ----- [name: ...] ----- 或 ----- [port: ...] ----- 分隔线。标签写的是你查询的原始目标,不是解析后的进程名——比如 [port: 5432] 区块里实际显示的进程可能是 postgres。
七、总结
witr 用一条命令替代了“先 ss 看端口,再 ps 找 PID,再 pstree 看父进程”的手工串联流程。
如果你经常在本地同时跑多个服务、容器和开发服务器,它会显著缩短“这东西到底是哪来的”这个问题的排查时间。