███████╗ ██████╗ ███╗ ██╗ █████╗ ██████╗
██╔════╝██╔═══██╗████╗ ██║██╔══██╗██╔══██╗
███████╗██║ ██║██╔██╗ ██║███████║██████╔╝
╚════██║██║ ██║██║╚██╗██║██╔══██║██╔══██║
███████║╚██████╔╝██║ ╚████║██║ ██║██║ ██║
╚══════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝
了解你机器上正在运行什么。
我厌倦了每次端口被占用时都要运行 lsof -iTCP -sTCP:LISTEN | grep ...,然后花一分钟弄清楚是 Docker 容器还是来自另一个工作树的孤立开发服务器。所以我构建了 sonar。
它可以显示所有在本地主机上监听的进程,包括 Docker 容器名称、Compose 项目、资源使用情况以及可点击的 URL。你可以按端口号杀死进程、查看日志、进入容器外壳,以及更多操作。
$ sonar list
PORT PROCESS CONTAINER IMAGE CPORT URL
1780 proxy (traefik:3.0) my-app-proxy-1 traefik:3.0 80 http://localhost:1780
3000 next-server (v16.1.6) http://localhost:3000
5432 db (postgres:17) my-app-db-1 postgres:17 5432 http://localhost:5432
6873 frontend (frontend:latest) my-app-frontend-1 frontend:latest 5173 http://localhost:6873
9700 backend (backend:latest) my-app-backend-1 backend:latest 8000 http://localhost:9700
5 个端口(4 个 Docker,1 个用户)
brew install raskrebs/sonar/sonar
在 macOS 上,这还会安装 sonar-tray 菜单栏应用。
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | bash
将最新的二进制文件下载到 ~/.local/bin,并在需要时将其添加到 PATH。重新启动终端或执行 source ~/.zshrc。
在 Windows(PowerShell)上:
irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex
自定义安装位置:
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_INSTALL_DIR=/usr/local/bin bash
安装特定版本:
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_VERSION=vX.Y.Z bash
$env:SONAR_VERSION="vX.Y.Z"; irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex
go install github.com/raskrebs/sonar@latest
注意:
go install只安装 CLI。菜单栏托盘应用(sonar tray)是原生的 Swift 二进制文件,必须单独构建——参见下面的托盘应用。
Shell 补全(按 Tab 补全端口号):
sonar completion zsh > "${fpath[1]}/_sonar" # zsh
sonar completion bash > /etc/bash_completion.d/sonar # bash
sonar completion fish | source # fish
sonar list # 显示所有端口
sonar list --stats # 包含 CPU、内存、状态、运行时间
sonar list --filter docker # 仅显示 Docker 端口
sonar list --sort name # 按进程名排序
sonar list --json # JSON 输出
sonar list -a # 包含桌面应用
sonar list -c port,cpu,mem,uptime,state # 自定义列
sonar list --health # 运行 HTTP 健康检查
sonar list --host user@server # 通过 SSH 扫描远程机器
默认情况下,sonar 会隐藏那些监听 TCP 端口但与开发无关的桌面应用和系统服务——比如 Figma、Discord、Spotify、ControlCenter、AirPlay 以及其他 macOS .app 包和 /System/Library/ 守护进程。使用 -a 包含它们。
可用列:port、process、pid、type、url、cpu、mem、threads、uptime、state、connections、health、latency、container、image、containerport、、、、、
sonar info 3000
显示端口的所有信息:完整命令、用户、绑定地址、CPU/内存/线程数、运行时间、健康检查结果以及 Docker 细节(如果适用)。
sonar kill 3000 # SIGTERM
sonar kill 3000 -f # SIGKILL
sonar kill-all --filter docker # 停止所有 Docker 容器
sonar kill-all --project my-app # 停止一个 Compose 项目
sonar kill-all --filter user -y # 跳过确认
Docker 容器使用 docker stop 停止,而不是发送信号。
sonar logs 3000
对于 Docker 容器,运行 docker logs -f。对于原生进程,通过 lsof 发现日志文件并跟踪。macOS 上回退到 log stream,Linux 上回退到 /proc/<pid>/fd。
sonar attach 3000 # 进入 Docker 容器外壳,或 TCP 连接
sonar attach 3000 --shell bash # 指定外壳
sonar watch # 每2秒轮询,显示差异
sonar watch --stats # 实时资源统计(类似 docker stats)
sonar watch -i 500ms # 更快的轮询
sonar watch --notify # 端口上线/下线时桌面通知
sonar watch --host user@server # 监控远程机器
sonar graph # 显示哪些服务相互通信
sonar graph --json # 结构化输出
sonar graph --dot # Graphviz DOT 格式
显示监听端口之间的已建立连接(例如,你的后端连接 PostgreSQL)。
为项目保存一组预期端口,然后检查它们是否全部运行或关闭:
sonar profile create my-app # 快照当前端口
sonar profile list # 列出已保存的配置文件
sonar profile show my-app # 显示配置文件详情
sonar up my-app # 检查预期端口是否都在运行
sonar down my-app # 停止配置文件中的所有端口
sonar wait 5432 # 阻塞直到端口接受连接
sonar wait 5432 3000 6379 # 等待多个端口
sonar wait 5432 --timeout 30s # 30秒后超时失败
sonar wait 5432 --http # 等待 HTTP 200,不仅仅是 TCP 开放
sonar wait 5432 --http=/health # 检查特定端点
sonar wait 5432 -i 500ms # 自定义轮询间隔
sonar wait 5432 -q # 无输出,仅返回退出码(用于脚本)
对于在 docker compose up -d 或后台服务周围编写脚本很有用。--http 标志等待实际的 HTTP 200-399 响应,而不仅仅是 TCP 套接字,这能捕获那些在真正准备好之前就接受连接的服务。使用 --http=/health 检查特定端点。退出码:0(就绪)、1(超时)、2(中断)。
docker compose up -d
sonar wait 5432 3000 --timeout 60s && npm run migrate && npm run test
sonar map 6873 3002
代理流量,使得端口 6873 上的服务也可在端口 3002 上使用。
sonar next # 从 3000 开始的下一个空闲端口
sonar next 8000 # 从 8000 开始的下一个空闲端口
sonar next 3000-3100 # 范围内第一个空闲端口
sonar next -n 3 # 3 个连续空闲端口
sonar next --json # JSON 输出
sonar open 3000 # 在浏览器中打开
sonar tray # 菜单栏应用,显示实时统计(macOS)
sonar --no-color # 禁用颜色(也尊重 NO_COLOR 环境变量)
--stats 标志获取每个进程和每个容器的资源使用情况。对于 Docker 容器,它使用 Docker 引擎 API 获取准确的每个容器指标。不使用 --stats 时,sonar 立即返回。
sonar 从 ~/.config/sonar/config.yaml 读取可选默认值。该文件是可选的——没有它时,使用内置默认值。命令行标志始终覆盖配置文件。
创建初始文件:
sonar config init # 写入带注释的模板
sonar config path # 打印文件位置
sonar config edit # 在 $EDITOR 中打开
示例配置:
list:
columns: [port, process, container, image, containerport, url]
sort: port # port | pid | name | type
filter: "" # docker | user | system | "" (全部)
all: false # 默认包含桌面应用
color: true # 设为 false 禁用彩色输出
services: # 标记自定义/未知端口
9000: php-fpm
5050: my-dashboard
无效值会被忽略并显示警告;sonar 继续使用默认值。
菜单栏托盘应用(仅 macOS)是一个原生的 Swift 二进制文件,在菜单栏中显示实时端口统计信息。如果你通过安装脚本或 GitHub 发布版安装了 sonar,托盘二进制文件(sonar-tray)会自动包含。
如果通过 go install 安装,请手动构建:
swiftc -O -o sonar-tray tray/SonarTray.swift -target arm64-apple-macos13
然后将 sonar-tray 移动到 $PATH 中的某个位置,并运行:
sonar tray
lsof)ss)netstat)感谢所有为 sonar 做出贡献的人!
composeprojectuserbindip