
witr:为什么这个进程在运行?
前言:一个永恒的问题
2026-08-13 11:05 GMT+8
系统管理员和开发者经常会遇到一个永恒的问题:
为什么这个进程在运行?
场景:
- 发现端口被占用,不知道是哪个进程
- 看到容器在运行,不知道是谁启动的
- 看到文件被锁定,不知道是哪个进程持有的
- 看到服务在运行,不知道启动链路
传统工具的局限:
传统工具(ps, top, lsof, ss, systemctl, docker ps)只能告诉你:
- ✅ What:什么在运行
- ❌ Why:为什么在运行
你需要手动在多个工具之间切换,手动关联输出,手动推断因果链。
今天介绍 witr:
Trace any process, port, container, or file back to the exact chain that started it
将任何进程、端口、容器或文件追踪回启动它的精确链条
一、项目概览
" witr 是一个系统追踪工具,用于回答"为什么这个在运行"这个问题。
一句话说清楚:
显示任何运行中事物的完整启动链路,回答"为什么这个在运行"
项目地址:https://github.com/pranshuparmar/witr 在线体验:https://pranshuparmar.github.io/witr/ 开源协议:未明确(开源仓库) 支持平台:Linux, macOS, Windows, FreeBSD
核心特性
单一目标:
- 回答一个问题:Why is this running?
完整的因果链:
- 显示进程、端口、容器、文件的完整启动链路
- 从 systemd → PM2 → node 的完整链条
- 从 docker-compose → 容器 → 进程的完整链条
交互式 TUI:
- 实时、可排序、可过滤的进程列表
- 端口、容器、文件锁的实时监控
- 深入进程详情(环境变量、工作目录、套接字...)
- 发送信号(Kill, Terminate, Pause, Resume)
机器可读输出:
- JSON 格式输出
- 可脚本化
- 可集成到其他工具
二、为什么需要 witr?
传统工具的问题
工具分散:
ps查看进程lsof查看打开的文件ss查看网络连接systemctl查看服务docker ps查看容器- ...
信息碎片化:
- 每个工具显示一部分信息
- 需要手动关联
- 需要手动推断
因果链隐藏:
- 看到进程在运行
- 但不知道是谁启动的
- 也不知道启动命令是什么
witr 的解决方案
统一视图:
- 一个工具查看所有信息
- 进程、端口、容器、文件锁
- 统一的数据模型
完整的因果链:
- 显示完整的启动链路
- systemd → PM2 → node
- docker-compose → 容器 → 进程
- SSH → shell → python
交互式探索:
- TUI 实时监控
- 深入进程详情
- 发送信号操作
三、核心功能
1. 进程追踪
功能:
- 查看所有运行进程
- 显示完整的进程树
- 显示启动命令
- 显示环境变量、工作目录
示例:
witr node输出:
node (PID: 1234)
└── PM2 (PID: 567)
└── systemd (PID: 1)2. 端口追踪
功能:
- 查看所有监听端口
- 显示占用端口的进程
- 显示完整的启动链路
示例:
witr -p 8080输出:
:8080 (LISTEN)
└── nginx (PID: 890)
└── systemd (PID: 1)3. 容器追踪
功能:
- 支持多种容器运行时(Docker, Podman, nerdctl, K8s/crictl, Incus, LXC, LXD, FreeBSD jails)
- 显示容器信息(名称、镜像、状态、端口)
- 显示容器内的进程
- 显示挂载点、网络、compose 项目元数据
示例:
witr -c web-server输出:
web-server (Docker)
├── Image: nginx:latest
├── Status: running
├── Ports: 80:80, 443:443
└── Process: nginx (PID: 123)
└── dockerd (PID: 456)
└── systemd (PID: 1)4. 文件锁追踪
功能:
- 查看系统范围的文件锁
- 支持 POSIX/FLOCK(Linux)
- 支持 lsof-derived(macOS/FreeBSD)
- 显示锁定进程
示例:
witr -l /var/lib/dpkg/lock输出:
/var/lib/dpkg/lock (FLOCK)
└── apt (PID: 789)
└── systemd (PID: 1)四、交互式 TUI
启动 TUI
无参数运行:
witr或使用 -i 标志:
witr -i四个标签页
1. Processes Tab:
- 实时、可排序、可过滤的进程列表
- 侧边栏显示高亮进程的祖先树
- 深入进程详情(环境变量、工作目录、套接字、文件上下文...)
2. Ports Tab:
- 打开/监听端口列表
- 侧边栏显示拥有进程
- 按
a切换 LISTEN-only / ALL 模式
3. Containers Tab:
- 所有运行容器的统一列表
- 支持多种容器运行时
- 显示容器名称、镜像、状态、端口、命令
- 每个容器的详细视图(挂载点、网络、compose 项目元数据)
4. Locks Tab:
- 系统范围的文件锁
- 按
a切换到"所有打开的文件"模式 - 按
/搜索
进程操作
发送信号(仅 Unix):
- Kill(SIGKILL)
- Terminate(SIGTERM)
- Pause(SIGSTOP)
- Resume(SIGCONT)
Renice:
- 调整进程优先级
其他特性
鼠标支持:
- 导航、排序列、点击行
自适应主题:
- 自动适配亮色/暗色终端背景
自动刷新:
- 自适应刷新频率(3 秒开始,负载下后退)
五、快速开始
安装
Unix (Linux, macOS, FreeBSD):
curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex验证安装
witr --version
man witr在线体验
访问 https://pranshuparmar.github.io/witr/:
- 调查模拟的 Linux 盒子
- 引导教程和自由沙盒
- 无需安装
六、使用示例
示例 1:查找占用端口的进程
场景:端口 8080 被占用
传统方法:
lsof -i :8080
ps -p <PID>
# 然后手动追踪父进程使用 witr:
witr -p 8080输出:
:8080 (LISTEN)
└── nginx (PID: 890, CMD: nginx -g daemon off;)
└── systemd (PID: 1)示例 2:追踪容器进程
场景:查看容器内的进程
传统方法:
docker ps
docker exec <container> ps aux
# 然后手动关联使用 witr:
witr -c web-server输出:
web-server (Docker)
├── Image: nginx:latest
├── Status: running
├── Ports: 80:80, 443:443
└── Process: nginx (PID: 123)
└── dockerd (PID: 456)
└── systemd (PID: 1)示例 3:查找文件锁
场景:文件被锁定
传统方法:
lsof /var/lib/dpkg/lock
ps -p <PID>使用 witr:
witr -l /var/lib/dpkg/lock输出:
/var/lib/dpkg/lock (FLOCK)
└── apt (PID: 789, CMD: apt upgrade)
└── systemd (PID: 1)示例 4:追踪进程树
场景:查看完整的进程树
传统方法:
ps auxf
# 手动追踪父子关系使用 witr:
witr node输出:
node (PID: 1234, CMD: node server.js)
└── PM2 (PID: 567, CMD: PM2)
└── systemd (PID: 1)示例 5:TUI 深入进程详情
场景:深入了解一个进程
使用 witr TUI:
witr
# 在 Processes Tab 中选中一个进程
# 按 Enter 深入详情显示内容:
- 完整的祖先树
- 子进程
- 环境变量
- 工作目录
- 套接字
- 文件上下文
- ...
七、高级特性
JSON 输出
机器可读输出:
witr -p 8080 --json输出:
{
"type": "port",
"port": 8080,
"protocol": "tcp",
"state": "LISTEN",
"chain": [
{
"pid": 890,
"name": "nginx",
"cmd": "nginx -g daemon off;"
},
{
"pid": 1,
"name": "systemd",
"cmd": "systemd"
}
]
}Shell 补全
启用 Tab 补全:
Bash:
eval "$(witr completion bash)"Zsh:
eval "$(witr completion zsh)"Fish:
witr completion fish | sourcePowerShell:
witr completion powershell | Out-String | Invoke-Expression八、实际应用场景
场景 1:排查端口占用
场景:应用无法启动,提示端口被占用
使用 witr:
witr -p 8080输出:
:8080 (LISTEN)
└── nginx (PID: 890)
└── systemd (PID: 1)操作:
- 发现是 nginx 占用
- 可以选择 Kill nginx
- 或者修改应用端口
场景 2:追踪容器启动链路
场景:容器在运行,不知道是谁启动的
使用 witr:
witr -c web-server输出:
web-server (Docker)
└── docker-compose (PID: 456)
└── SSH session (PID: 123)
└── systemd (PID: 1)操作:
- 发现是 docker-compose 启动的
- 可以找到 docker-compose.yml 文件
- 可以了解完整的启动链路
场景 3:排查文件锁
场景:apt 更新失败,提示文件被锁定
使用 witr:
witr -l /var/lib/dpkg/lock输出:
/var/lib/dpkg/lock (FLOCK)
└── apt (PID: 789)
└── systemd (PID: 1)操作:
- 发现是 apt 进程持有锁
- 可以等待 apt 完成
- 或者 Kill apt 进程
场景 4:监控系统状态
场景:实时监控系统状态
使用 witr TUI:
witr操作:
- 在 Processes Tab 查看进程
- 在 Ports Tab 查看端口
- 在 Containers Tab 查看容器
- 在 Locks Tab 查看文件锁
场景 5:调试启动脚本
场景:服务启动脚本不工作
使用 witr:
witr <service-name>输出:
<service-name> (PID: 1234)
└── systemd (PID: 1)操作:
- 查看启动命令
- 查看环境变量
- 查看工作目录
- 调试启动脚本
九、与传统工具的对比
vs ps
| 维度 | ps | witr |
|---|---|---|
| 显示内容 | 进程列表 | 进程 + 完整启动链路 |
| 因果链 | 手动追踪 | 自动显示 |
| 格式 | 固定格式 | 可读树形 / JSON |
| 交互式 | 无 | TUI |
vs lsof
| 维度 | lsof | witr |
|---|---|---|
| 显示内容 | 打开的文件 | 文件锁 + 启动链路 |
| 因果链 | 手动追踪 | 自动显示 |
| 格式 | 固定格式 | 可读树形 / JSON |
| 交互式 | 无 | TUI |
vs systemctl
| 维度 | systemctl | witr |
|---|---|---|
| 显示内容 | 服务状态 | 服务 + 进程 + 启动链路 |
| 因果链 | 手动追踪 | 自动显示 |
| 范围 | systemd 服务 | 所有进程/端口/容器 |
| 交互式 | 无 | TUI |
vs docker ps
| 维度 | docker ps | witr |
|---|---|---|
| 显示内容 | 容器列表 | 容器 + 进程 + 启动链路 |
| 容器运行时 | Docker | Docker + Podman + nerdctl + K8s + ... |
| 因果链 | 手动追踪 | 自动显示 |
| 交互式 | 无 | TUI |
十、核心价值
1. 完整的因果链
从"what"到"why":
- 传统工具显示"什么在运行"
- witr 显示"为什么在运行"
完整的启动链路:
- systemd → PM2 → node
- docker-compose → 容器 → 进程
- SSH → shell → python
2. 统一的视图
一个工具,所有信息:
- 进程、端口、容器、文件锁
- 统一的数据模型
- 统一的输出格式
交互式探索:
- TUI 实时监控
- 深入进程详情
- 发送信号操作
3. 机器可读
JSON 输出:
- 可脚本化
- 可集成到其他工具
- 可自动化
4. 多平台支持
跨平台:
- Linux, macOS, Windows, FreeBSD
- 统一的体验
- 统一的功能
十一、总结
核心问题
为什么这个进程在运行?
传统工具的局限
工具分散:
- 需要多个工具
- 需要手动关联
- 需要手动推断
信息碎片化:
- 每个工具显示一部分信息
- 因果链隐藏
- 启动命令丢失
witr 的解决方案
统一视图:
- 一个工具查看所有信息
- 进程、端口、容器、文件锁
- 统一的数据模型
完整的因果链:
- 显示完整的启动链路
- 从根进程到当前进程
- 从根服务到当前容器
交互式探索:
- TUI 实时监控
- 深入进程详情
- 发送信号操作
为什么选择 witr?
1. 完整的因果链
- 从"what"到"why"
- 显示完整的启动链路
2. 统一的视图
- 一个工具,所有信息
- 进程、端口、容器、文件锁
3. 交互式探索
- TUI 实时监控
- 深入进程详情
- 发送信号操作
4. 机器可读
- JSON 输出
- 可脚本化
- 可集成
5. 多平台支持
- Linux, macOS, Windows, FreeBSD
- 统一的体验
- 统一的功能
记住
witr 回答一个永恒的问题:为什么这个进程在运行?
显示任何运行中事物的完整启动链路。
从 systemd → PM2 → node,从 docker-compose → 容器 → 进程。
附:资源链接
项目资源:
- GitHub:https://github.com/pranshuparmar/witr
- 在线体验:https://pranshuparmar.github.io/witr/
- 故事:https://medium.com/@pranshu.parmar/witr-why-is-this-running-a9a97cbedd18
- Hacker News:https://news.ycombinator.com/item?id=46392910
安装方式:
Unix (Linux, macOS, FreeBSD):
curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex包管理器:
- Homebrew:
brew install witr - Conda:
conda install -c conda-forge witr - APT:
sudo apt install witr - Winget:
winget install -e --id PranshuParmar.witr
使用示例:
# 查看占用端口的进程
witr -p 8080
# 查看容器
witr -c web-server
# 查看文件锁
witr -l /var/lib/dpkg/lock
# 查看进程
witr node
# 启动 TUI
witr
# 或
witr -i
# JSON 输出
witr -p 8080 --json