综合 端口被谁占用、容器里跑的是什么:用 witr 回溯进程的启动链

2026-09-14 21:31:21

端口被谁占用、容器里跑的是什么:用 witr 回溯进程的启动链

pstop 告诉你什么在跑,lsofss 告诉你是谁占着端口,systemctldocker ps 告诉你服务状态。但这些都是状态:拿到几份输出,还得自己把信息串起来,才能回答"这东西为什么在跑"。

服务背后往往隔着好几层——supervisor、容器、shell、init——起因是间接的,也不在一个工具的视野里。witr 要回答的就是这一句:Why is this running? 它把进程、端口、容器、文件回溯到确切的启动链,输出可以是终端里的一行、机器可读的 JSON,或者交互式 TUI。

一切归到 PID

端口、服务、容器、文件,witr 都当作"进程问题"处理,最终映射到一个 PID。拿到 PID 之后,它构建一条解释"这个 PID 为什么存在"的因果链,回答四件事:在跑什么、怎么启动的、谁在维持它、它属于什么上下文。

安装

单个静态二进制,覆盖 Linux / macOS / FreeBSD / Windows。

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

包管理器:apt install witrbrew install witrconda install -c conda-forge witryay -S witr-binwinget install -e --id PranshuParmar.witrnpm install -g @pranshuparmar/witr、FreeBSD 用 pkg install witr

源码安装:

go install github.com/pranshuparmar/witr/cmd/witr@latest

TUI

直接运行 witr,或者 witr -i。四个 Tab:

  • Processes:进程列表,侧栏给出祖先树
  • Ports:监听端口和所属进程,按 a 在 LISTEN / ALL 之间切换
  • Containers:Docker、Podman、nerdctl、crictl、Incus、LXC、LXD、FreeBSD jail 统一列出
  • Locks:系统级文件锁,按 a 切换到所有打开文件

支持鼠标、跟随终端自适应主题、自动刷新(从 3 秒起,负载高时退避),也能直接从 UI 里发信号(Kill / Terminate / Pause / Resume),或在 Unix 上 renice。

关键 flags

-c, --container    查容器
--env          显示环境变量
-x, --exact        精确匹配
-f, --file         按文件查
-h, --help
-i, --interactive
--json         输出 JSON
--no-color
-p, --pid
-o, --port
-s, --short        只显示祖先链
-t, --tree         树形祖先链
--verbose
-v, --version
--warnings

位置参数按进程名/服务名做子串(模糊)匹配。多个目标可以混用,结果按顺序分段输出。

输出长什么样

witr node

Target      : node
Process     : node (pid 14233)
User        : pm2
Command     : node index.js
Started     : 2 days ago (Mon 2025-02-02 11:42:10 +05:30)
Why It Exists :
systemd (pid 1) → pm2 (pid 5034) → node (pid 14233)
Source      : pm2
Working Dir : /opt/apps/expense-manager
Git Repo    : expense-manager (main)
Sockets     : 127.0.0.1:5001 (TCP | LISTENING)

只想看链条,用 --short。比如 witr --port 5000 --short

systemd (pid 1) → PM2 v5.3.1: God (pid 1481580) → python (pid 1482060)

要看完整的树,witr --pid 143895 --tree 会打印 systemd → … → node 的树,最多带上 10 个子进程,并高亮目标本身。

几个具体场景

端口被谁占着witr -o 5000 直接给出端口对应的 PID 和它的启动来源,不用 ss 完再 lsofps -ef 一层层扒。

文件被谁占着witr --file /var/lib/dpkg/lock 解释谁持有这个文件。macOS 上没有 /proc,这一块更多依赖 lsof 一类工具的信息来推导。

容器里跑的是什么witr --container redis 跨运行时查找,加 --verbose 会输出 mounts / networks / compose metadata。

名字匹配到多个目标witr ng 会同时列出 nginx、nginx、ngrok 之类的匹配项,提示你用 --pid 精确定位,或者加 -x 做精确匹配。

不装也能先看效果: 提供了模拟 Linux 机器的引导教程和自由沙箱。

项目地址:

复制全文 生成海报 witr 进程排查 运维工具 CLI Go

推荐文章

程序员茄子在线接单