dsh-reaper:回收智能体会话遗留的端口与进程

前言

在 DeepSeek Harness(DSH)里用智能体跑前端或脚本时,常见流程是拉起 vite、next dev、文件监听或隧道。一轮对话结束、会话关闭后,这些进程往往仍在监听 5173、3000 等端口。下一次再启动开发服务就会遇到 EADDRINUSE,只好在任务管理器或 ps 里逐个猜哪个 node 是该杀的。

单纯「按端口号杀进程」的工具只能告诉你谁在占端口,却很难判断该不该杀:会不会误杀本机 MySQL、会不会把正在跑的 Harness 自己干掉、占端口的进程是否和当前工作区有关。dsh-reaper 是 DSH 社区插件(维护者 11111353535,分类为工作流),在盘点本机监听端点的基础上,为每个占用者打上归属与风险等级,先给出计划,只有在显式确认后才发送信号回收端口。

这是什么

dsh-reaper 的定位是:为 DeepSeek Harness 清点监听端点,把占用者与当前会话、工作区、系统服务区分开,预览将要终止的进程树,并在用户确认后回收端口。README 中的一句话概括是:找回智能体会话留下却未归还的孤儿开发服务与监听进程。

插件通过 Cordis 向 Harness 注册工具与斜杠命令;实现为纯 ESM JavaScript(lib/),依赖 node:* 与 @deepseek-ai/dsh-tools,由宿主解析,不捆绑可能覆盖宿主版本的依赖。

核心能力

扫描与分级

只读扫描会枚举本机监听端点(默认 TCP;配置或参数可包含 UDP),并结合进程表做归属判断。每个端点会得到一个 verdict,用于决定能否纳入「安全批量回收」:

verdict 含义 all: true 时是否默认选中
agent-spawned 源自当前 Harness 宿主进程的子进程 是
workspace 命令行中出现当前工作区路径 是
dev-server 形似开发服务、监听或隧道 否
unattributed 在监听但无法归因到本会话 否
system 系统进程或知名服务端口(如 3306) 否
protected 命中 neverKill / protectPorts,或持有 Harness 进程树 否

两条规则保证分级可信:扫描从自身 pid 向上遍历,拒绝终止整条祖先链及 Harness 所在进程树;持有知名服务端口的进程记为 system,all: true 不会选中,备注为 left alone 而非暗示可强制覆盖。

回收与安全默认值

回收是破坏性操作,默认极为保守:

  1. 未传 confirm: true 时只计算并返回计划,不向任何进程发信号。
  2. 计划包含完整后代闭包:杀 npm run dev 包装进程而不杀子进程会留下仍占端口的进程,插件按「最深子进程优先」排序后再发信号。
  3. 对 Harness 进程树、pid 0–4、neverKill 匹配项、protectPorts 上的占用者一律拒绝,即使用户显式传入 pid 也不可覆盖,并返回原因。
  4. 默认先发 SIGTERM;仅当 force: true 时才升级为 SIGKILL,仍存活的进程会在结果中报告。
  5. 发信号后会重新探测端口,报告 ports confirmed free 或 ports still held。

扫描在 Windows、Linux、macOS 上分别使用 PowerShell/netstat 回退、ss、lsof 等最佳努力枚举;某一数据源失败会在结果末尾以 degraded: ... 说明,归因可能变弱但不会静默失败。

安装与配置

在 DSH 中安装(命令来自官方 README):

dsh plugin add https://github.com/11111353535/dsh-reaper

若从本地目录安装而非 Git 托管地址,使用绝对路径:

dsh plugin add /absolute/path/to/dsh-reaper

按 profile 调参时,在安装器写入的 ~/.dsh/profiles/<profile>/cordis.patch.yml 对应条目中增加 config,例如:

- insert:
    - id: reaper
      name: 'dsh-reaper'
      config:
        neverKill: ['my-precious-daemon']
        protectPorts: [80, 443, 19387]
        includeUdp: false
        graceMs: 3000
        scanTimeoutMs: 20000
配置项 默认值 说明
neverKill [] 进程名或命令行子串,命中则永不发信号
protectPorts [] 占用这些端口的进程一律拒绝;Harness 自身 Web 端口会自动加入
includeUdp false 是否枚举 UDP;开发服务多为 TCP
graceMs 3000 SIGTERM 后等待多久再视为仍存活
scanTimeoutMs 20000 单次系统枚举的时间上限

典型用法

斜杠命令

/reap                  # 仅盘点
/reap --all            # 预览本会话可置信归因的全部端点
/reap --all --confirm  # 确认后执行回收
/reap 5173             # 预览回收单个端口
/reap 5173 3001 --confirm --force

盘点输出示例(来自 README,环境为 win32)会列出监听端点数、进程数、可回收数量,并按端口展示 verdict、pid、运行时长与命令行;系统服务与受保护进程会附带说明行。

工具接口

  • reaper_scan:只读全量扫描。可选 includeUdp、workspace(默认当前会话工作区)。
  • reaper_reap:生成计划;confirm: true 时执行。支持 pids、ports、all(仅 agent-spawned 与 workspace)、force、confirm(默认 false)。
  • reaper_free_port:针对单个 TCP 端口。端口已空闲则直接说明;无法归因或受保护则报告原因而不猜测。

智能体在对话中也可直接调用上述工具,行为与斜杠命令一致:先预览,再确认。

适用场景与注意

适合经常在 DSH 里让智能体启动/重启开发服务、又反复遇到端口占用的开发者。也适合在结束一轮长会话前,用 /reap 看清本机还有哪些监听与当前工作区或 Harness 相关,再决定是否 --all --confirm。

使用前请注意:

  1. 插件以当前 DSH 进程权限运行,发信号的对象是操作系统上的真实进程;安装前建议阅读 GitHub 仓库 源码与 MIT 许可证。
  2. 社区目录 SkillHub 插件页 与 GitHub 为独立信息源,与 DeepSeek / 幻方无官方从属关系;星标与版本以各页面当时显示为准(package.json 当前版本为 0.1.0)。
  3. 勿指望用端口号或 pid 绕过 protected / system 保护;需要长期保留的守护进程应写入 neverKill 或 protectPorts。

结尾

dsh-reaper 把「谁占着端口」和「能不能杀」拆开处理:先分级、再闭包计划、最后才在确认后回收,并验证端口是否释放。若你主要在 DSH 工作流里做本地开发,它是对付 EADDRINUSE 与孤儿 node 进程的一条可核对路径。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜