服务器上跑着一堆东西:Docker 容器、pm2 进程、systemd 服务。docker ps 能看到容器,ps 能看到进程,ss 能看到端口,但”它为什么在跑、谁把它拉起来的”,得自己把几个命令的输出拼起来猜。

witr(Why is this running)就是解决这个问题的:一条命令,把进程、端口、容器、文件追溯回启动它的完整链路。CLI 和交互式 TUI 都有。

项目简介

  • Go 编写,Apache-2.0 开源,GitHub 上约 1.8 万 star
  • 定位是回答”为什么这个东西在运行”,输出从 systemd 到目标进程的完整因果链
  • 支持 Linux、macOS、FreeBSD、Windows,发布单文件静态二进制
  • 容器查询覆盖 Docker、Podman、nerdctl、K8s/crictl、Incus、LXC、LXD、FreeBSD jails
  • 输出支持普通文本、短链、树状、JSON,方便脚本和监控使用

安装

Linux / macOS 一行命令装最新版:

1
curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bash

脚本会自动识别系统和 CPU 架构,装到 /usr/local/bin。Windows 在 PowerShell 里执行:

1
irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex

装完验证:

1
witr --version

其他常用安装方式:

  • Debian/Ubuntu:sudo apt install witr(Ubuntu 26.04+、Debian sid)
  • macOS:brew install witr
  • Arch:yay -S witr-bin
  • 跨平台:npm install -g @pranshuparmar/witrconda install -c conda-forge witr
  • 源码安装:go install github.com/pranshuparmar/witr/cmd/witr@latest

快速上手

1. 查进程是谁拉起来的

1
witr node

输出直接给出因果链:

1
2
3
4
5
Target      : node
Process : node (pid 14233)
Command : node index.js
Why It Exists:
systemd (pid 1) → pm2 (pid 5034) → node (pid 14233)

一眼就能看到:systemd 起了 pm2,pm2 起了你的 node。

2. 端口被谁占着

1
witr --port 8080

只想看链路的话加 -s(short):

1
witr -o 8080 -s

3. 按 PID 看父子树

1
witr --pid 12345 --tree

会画出完整的祖先和子进程树,并高亮目标进程。

4. 查容器

1
witr --container redis

不用管它跑在 Docker、Podman 还是 K8s 里,witr 自动在所有已检测到的运行时中查找,按容器名、镜像、命令、compose 项目都能匹配。想看挂载、网络、compose 元数据:

1
witr -c redis --verbose

多个目标可以混着查:

1
witr nginx --port 5432 --pid 1234

5. 文件被谁占用

1
witr --file /var/lib/dpkg/lock

6. 交互式界面

直接输入 witrwitr -i 进入 TUI,有四个标签页:

  • Processes:进程列表,旁边显示选中进程的祖先树
  • Ports:监听端口和归属进程,按 a 切换”仅监听/全部”
  • Containers:所有运行中的容器统一列表,可查看挂载、网络、启动命令详情
  • Locks:系统文件锁,按 a 切换为”全部打开文件”

进程页里能直接对进程发信号(Kill、暂停、继续)或调整优先级(Unix 系统),支持鼠标操作,列表自动刷新。

进阶用法

  • 脚本处理用 JSON:witr --port 5000 --json
  • 默认是子串模糊匹配,需要精确匹配加 -xwitr nginx -x,避免把 ngrok 也匹配进来
  • 开启 Shell 补全:zsh 在 ~/.zshrceval "$(witr completion zsh)"
  • 退出码:0 表示找到且无警告,其余值可用于监控脚本
  • 不想安装可以先试玩:README 里提供在线模拟沙箱,可以跟着教程体验

卸载

脚本/手动安装的:

1
sudo rm -f /usr/local/bin/witr /usr/local/share/man/man1/witr.1

包管理器安装的用对应命令卸载(如 brew uninstall witr)。

适合哪些人

  • 运维和 DevOps:排查”端口被谁占着””容器为什么在跑”
  • 自托管玩家:一堆 docker compose、pm2、systemd 服务,早就忘了谁拉谁
  • 安全应急响应:快速梳理可疑进程的启动链路和上下文
  • Linux 新手:想搞懂 systemd 和服务进程的关系,比对着 ps 输出猜直观得多

不太适合只想知道”现在跑了什么”的人——这种需求 psdocker ps 已经够了,witr 的强项是回答”为什么”。

优点

  1. 一个命令讲清因果链,省去 pssssystemctldocker ps 来回对照
  2. 容器查询跨运行时统一,Docker、Podman、K8s、LXC 等一套命令搞定
  3. 单文件二进制,安装简单,跨平台
  4. TUI 直观,还能直接在界面里管理进程
  5. 输出模式多,短链、树、JSON 都有,适合脚本和监控
  6. 项目活跃:1.8 万 star、30+ 贡献者,进了 Debian、FreeBSD 等发行版仓库

缺点

  1. 项目还年轻,Windows 支持较新,个别功能可能没对齐
  2. “为什么”是尽力推断:依赖进程树和父进程信息,遇到 PID 复用、进程改名的场景可能不准
  3. 查别人的进程、系统级文件锁需要足够权限(root 或管理员)
  4. 查 K8s 容器要求机器上有 crictl,查 LXC 要求有对应运行时工具,缺了查不到
  5. 发行版仓库版本可能滞后,apt 装的未必是最新版
  6. 文档只有英文,中文用户需要习惯一下

witr 不是 ps 的替代品,它补上的是 ps 缺的那一块:从”看到什么”到”知道为什么”。排查服务器问题、理清自托管服务依赖的时候,比一条条翻日志省事得多,值得放进运维工具包。