cg-shell-janitor:清理 DSH 在 Windows 上遗留的 runner 进程

前言

在 Windows 上跑 DSH,每次 shell 调用都会拉起一个私有 runner 进程。命令跑完,这个 runner 本该自己退出,但实测它经常留下来:README 记录的一台 DSH Desktop 0.2.x 上,一个工作会话里攒了 8 个,占 1127 MB,最老的一个已经空转了四个半小时。@deepseek-ai/dsh-subprocess-local 和 dsh-ops 都没有暴露 shell 生命周期的设置项,也就是说没什么可配置的。cg-shell-janitor 就是针对这个问题的绕开方案,由 DonGeeo87 维护,分类是 admin-security。

下面介绍它的工作方式、配置项和安装方法。

问题出在哪

Windows 上每次 dsh shell 调用都会启动一个私有 runner:

"DeepSeek Harness.exe" "...\dsh-subprocess-local\lib\runner.js" -- ...\bash.exe -c "<your command>"

这个 runner 持有命令的 Win32 Job。命令结束时它理应通过自己的 poll() 关闭空 Job 并调用 finish(0),实际却常常继续存活,持续占着内存。这正是 cg-shell-janitor 要清理的对象。

核心功能

插件每 intervalSeconds 采样一次,查找 DSH runner 进程,关闭其中确实无事可干的。关闭 runner 会释放它持有的 Win32 Job,这与 DSH 自己管理子进程的语义一致。它只在以下条件全部满足时才动手:

  1. runner 的父进程仍然是 DSH host 进程。
  2. runner 没有活着的子进程,也就是 bash.exe 已经退出。
  3. 它曾经被观察到的子进程也没有还活着的,说明它没有在照看后台进程。树在每次采样时重新学习,所以用 & 留下一个 server 的那条命令,它的 runner 仍受保护。
  4. 它存在的时间超过 idleMinutes。
  5. 周围没有无法归因的类 daemon 孤儿进程。如果有,插件进入保守模式,本轮什么都不关。

启动后的第一次采样只观察,不决定,先摸清当前进程树。插件不删除任何文件,除了泄漏的 runner 本身,不碰任何进程。

README 给出的实测数据来自同一台机器、同一会话,第一次真实周期之后:存活 runner 从 8 个(1127 MB)降到 2 个(288 MB,两个都有正在跑的 shell),空闲内存从 3.37 GB 升到 5.78 GB,总进程数从 298 降到 240。

安装

README 提到两种途径:从 dsh-market 目录一键安装,或者从本地 checkout 安装。本地安装命令是:

dsh plugin --profile <your-profile> add <path-to-this-directory>

完成后重启 harness。

卸载命令:

dsh plugin --profile <your-profile> remove cg-shell-janitor

配置

配置写在 cordis.patch.yml 里:

Key 默认值 含义
enabled true 关闭周期但不卸载插件
dryRun false 只记录将要关闭的进程,不做实际操作
intervalSeconds 180 采样间隔(取值 30–3600)
idleMinutes 5 关闭前的最短存活时长(取值 1–1440)
reapOnStartup true 启动后 20 秒做第一次采样

一个周期大约每三分钟占用单核 2 秒,因为只通过 PowerShell 跑一次 Get-CimInstance 查询。如果这对你来说也有影响,把 intervalSeconds 调大即可。

日志写在 ~/.dsh/shell-janitor.log,按 256 KB 轮转。

适用场景与注意

面向在 Windows 上长时间使用 DSH、被泄漏 runner 累积占内存困扰的开发者。需要留意几点:

  • 仅限 Windows。 泄漏出在持有 Win32 Job 的 runner 上,其他平台上插件只记一行日志不做任何事。
  • 这是一个启发式方案,不是修复。真正的修复在上游:runner 本该自己退出。
  • 插件加载前已创建、且 shell 已经退出的 runner,在插件侧没有子进程记录。它一旦超过 idleMinutes 仍会被关闭,因为条件 5 只拦那些插件完全无法归因的孤儿进程。
  • 如果你刻意从 shell 命令里保活一个 daemon,而插件从未观察到那条命令,这个 daemon 只受保守模式保护,而不是精确匹配保护。

插件以当前 dsh 进程的权限运行,安装前建议先查看它的源码(README 和 cordis.patch.yml)并确认许可证:MIT。

小结

cg-shell-janitor 做的事情很窄:周期性找出 Windows 上已经无事可做却没退出的 DSH runner 并关掉,单个约能回收 140 MB。它不能替代上游修复,但在配置项缺位的情况下提供了可用的清理手段。

  • 社区目录页:https://www.skillhub.cn/plugins/DonGeeo87/cg-shell-janitor
  • GitHub:https://github.com/DonGeeo87/cg-shell-janitor
羽毛球分组比赛记分
小程序二维码

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

小夜