DeepSeek Harness 的 %TEMP% 被 dsh-workspace-changes 占满怎么清理

故障排查发布于 2026-10-20作者: DeepSeek Plugin 插件市场
DeepSeek HarnessDSHworkspace-changes临时目录磁盘清理mkdtempTEMP
DeepSeek Harness 的 workspace-changes 只在会话 dispose 时删除 scratch 目录,崩溃、强退或升级重启都会在 %TEMP% 留下 dsh-workspace-changes-*,单机可累积几十 GB。给存量清理、启动清扫、pid/owner 回收与缓存迁入工作区四条路。

打开 %TEMP%,看到一堆 dsh-workspace-changes- 开头的目录,单个 1 到 6 GB,合计几十 GB——这是 DeepSeek Harness(DSH)的 workspace-changes 在会话没走到 dispose 时留下的孤儿。 报告者的机器上累积到 60.45 GB、131 个目录、302,971 个文件,而整个 %TEMP% 是 168 GB。社区在 master 上核对后确认形状一致,不是某个旧版本的特例(#10336)。

这类泄漏不会报错、不会拖慢启动,只会悄悄吃掉系统盘。下面先教你确认,再给清理与根治路线。

DeepSeek Harness 临时目录泄漏怎么确认:判据与 dispose 机制

判据是「目录名前缀固定、位于系统临时根、修改时间对应某次异常退出或升级重启」。 四步核对:

  1. 在 PowerShell 里列出匹配前缀的目录,并统计总大小。预期:得到目录数与 GB 数,量级与讨论里的样本接近或更小。
  2. 按修改时间排序,看最近一次写入对应哪个时间点。预期:多数集中在崩溃、强退或更新重启附近。
  3. 检查目录内部结构。预期:非 git 工作区能看到 objects/ 与 captures/,说明是文件捕获的数据。
  4. 确认当前没有 DSH 会话正在使用它们。预期:DSH 已完全退出,或目录修改时间明显早于当前会话开始时间。

macOS 与 Linux 上同样存在这类目录,只是临时根换成了系统的 TMPDIR,前缀不变。

机制上,删除动作只挂在 session/disposed 上,而这个事件在崩溃、强退、kill、更新重启时都不会发出,启动时也没有任何清扫。 据社区核对源码,链路是:

  1. 每个会话首次用到 workspace-changes 时,调用 mkdtemp 在临时根下建一个带随机后缀的目录。
  2. 目录里按需写入对象与捕获文件,单文件受 maxFileBytes 限制。
  3. 唯一的删除点是 dispose(),通过 session/disposed 触发。
  4. 进程异常结束时事件不发出,目录原样留在磁盘上。
  5. 下一次启动不扫描历史目录,泄漏因此只增不减。

还有一个放大因素:单个会话只要碰过几个大二进制,captures/ 就能长到几 GB。报告者的清单里,单个目录 1.1 到 6.8 GB、最多约 1.5 万个文件,所以「按天清理」对每周只跑一次大项目的机器并不够。

泄漏增长有多快

增长由「异常退出次数 × 单次会话碰过的文件体积」决定,和会话跑了多久关系不大。

  1. 每个异常结束的会话至少留下一个目录,目录数约等于异常退出次数。
  2. 目录大小取决于该会话碰过多少文件、单个文件多大,而不是会话时长。
  3. 若工作区里有构建产物或镜像层,单次会话就能留下数 GB。
  4. 因此「磁盘还剩多少」比「过了几天」更适合作为清理阈值。

DSH插件造成的存量目录怎么清理

清理本身很安全,前提是先确认没有活跃会话在使用;不要一边跑长任务一边删。 七步:

  1. 完全退出 DSH,包括托盘与后台进程。预期:任务管理器里没有 DSH 相关进程。
  2. 列出所有匹配目录并记录大小,先看清再动手。预期:得到一份可核对的清单。
  3. 先删修改时间早于 7 天的目录,保留最近几天的作为对照。预期:释放大部分空间,最近会话不受影响。
  4. 重新启动 DSH,新建一个会话并触发一次文件改动。预期:功能正常,新目录照常创建。
  5. 观察一天后,再决定是否清理剩余的老目录。预期:确认没有误删正在使用的数据。
  6. 再扫一次系统临时根,确认没有遗漏其它前缀的 DSH 临时目录。预期:只剩最近的活跃目录。
  7. 记录本次释放的空间与目录数,作为下次判断泄漏速度的基线。预期:有了可对比的数据。

删除前把清单另存一份;如果之后发现某次会话的变更记录缺失,至少知道删了哪些。不想自己写清扫逻辑的话,可以在 DSH Plugin Hub 找现成的临时目录清理插件,但别用按名字通配删除的那种。

DeepSeek Harness 路径一:启动时按前缀清扫

不改目录内容、只加一次启动扫描,是成本最低的根治方向;按修改时间判断,能覆盖绝大多数孤儿。 适合能改宿主启动流程的人。

  1. 在宿主启动的早期阶段,读取临时根并列出匹配 dsh-workspace-changes- 的目录。预期:拿到候选列表。
  2. 对每个目录读取修改时间,超过阈值(例如 24 小时)才进入删除队列。预期:正在使用的目录被排除。
  3. 删除失败只记日志,不阻塞启动。预期:权限或占用问题不会让 DSH 起不来。
  4. 首次上线先跑 dry-run,只打印将删列表。预期:人工核对一轮再真正启用。
  5. 补一个测试:造两个目录,一个旧一个新,确认只删旧的。预期:测试通过。

DeepSeek Harness 路径二:写入 pid/owner,定期回收

按时间清扫会误判「跑了一周的长会话」,写入持有者信息才能准确判断目录是否还有主人。 这也是讨论里更推荐的形状。

  1. 创建 scratch 目录后立刻写入一个 owner 文件,内容包含 pid、进程启动时间与会话 id。预期:每个目录都有可读的持有者信息。
  2. 回收时先读 owner,探测 pid 是否存活;pid 复用要用启动时间二次确认。预期:不会把新进程误认成旧持有者。
  3. 用定时任务回收超过一定时长、且持有者已不存在的目录。预期:泄漏在小时内被发现,而不是攒到几十 GB。
  4. 删除时先重命名成带删除标记的名字,再递归删除。预期:中途失败不会留下半个目录被下次误判。
  5. 记录每次回收的数量与字节数。预期:能从日志判断泄漏是否还在发生。

DeepSeek Harness 路径三:把缓存迁入工作区

把 scratch 根从系统临时目录换到工作区内的缓存目录,能让「删工作区」顺带清掉缓存,但会引入同步与仓库污染问题。 只适合特定场景。

  1. 选择一个工作区内的固定缓存目录,例如 .dsh/cache/workspace-changes。预期:路径确定,便于统一清理。
  2. 把该目录加入版本控制忽略规则与同步盘排除列表。预期:git status 干净,同步客户端不扫描。
  3. 修改创建逻辑,改用这个根目录,并在工作区删除时一并清理。预期:换工作区即清缓存。
  4. 评估工作区所在磁盘:网络盘或同步盘上不要启用。预期:采集延迟没有明显上升。
  5. 保留迁移前的存量清理步骤,否则老目录仍占着系统盘。预期:磁盘占用真正下降。

DeepSeek Harness 三条修法怎么选、边界在哪

先清存量,再决定要不要改代码;能改启动流程就选路径一,要长期准确就选路径二,工作区本身就是临时目录才考虑路径三。 四点提醒:

  1. 不要把「临时目录」理解成「可以随便删」:正在写入的对象被删,会让当前会话的变更视图缺块。
  2. 同目录下还有一类带 pid 的 spill 文件,它们的名字里就有持有者信息,清扫可以直接判断;workspace-changes 目录没有这个信息,所以更需要补 owner。
  3. 系统清理工具可能已经动过这些目录,排查时以实际存在为准,不要只信计划任务日志。
  4. 讨论里没有官方修复版本,0.1.7-rc.2 可复现、master 形状相同;相关工作区与任务问题另见 工作区与后台任务。
  5. 清理前后各记一次磁盘可用空间,确认释放量与被删目录的大小对得上,避免把别处的增长误算成泄漏。

常见问题

DeepSeek Harness 在 %TEMP% 留下 dsh-workspace-changes- 目录,能删吗?

确认没有 DeepSeek Harness 进程正在使用它们之后可以删。这些目录是 workspace-changes 为每个会话建的 scratch 数据,正常结束会话时会被删掉;留下的是崩溃或强退的孤儿。先完全退出 DSH,再按修改时间筛掉最近几小时的目录,删除更早的即可,不会影响会话历史。

为什么 DeepSeek Harness 正常关闭窗口后,临时目录还是留下来了?

DeepSeek Harness 只在 session/disposed 事件上删除目录,而关窗口不等于每个会话都走到 dispose。进程被强杀、更新时重启、系统休眠后终止,都不会触发这个回调;下一次启动也没有清扫逻辑。所以「关过窗口」不能保证目录已清理,要看目录的修改时间与当前是否有会话在跑。

怎么让 DeepSeek Harness 在下次启动时自动清掉这些孤儿目录,而不是每次手工删?

DeepSeek Harness 有两条路:启动时扫描 temp 根下匹配前缀的目录,按修改时间清理超过阈值的;或者创建目录时写入 pid 或 owner 文件,回收时判断持有进程是否还活着。前者不需要改目录内容,后者更准确,但要同时处理 pid 复用与启动时间。

DeepSeek Harness 把 workspace-changes 缓存迁进工作区,会污染 git 吗?

DeepSeek Harness 把缓存迁进工作区会带来仓库污染和同步压力。缓存放进工作区必须先加进忽略规则,否则会出现在 git 状态里;工作区若在同步盘或网络盘上,还会把大量对象同步出去,并显著拖慢采集。它适合工作区本身就是临时目录的场景,不适合长期项目目录。

相关术语

scratch 目录
scratch 目录是 workspace-changes 为单个会话创建的临时工作区副本,用来存放对象与文件捕获。它按会话隔离,正常销毁会话时删除,进程异常退出时不会被清理。— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
mkdtemp
mkdtemp 是创建带随机后缀的唯一临时目录的系统调用封装,保证并发创建不冲突。它只负责创建,不负责删除,生命周期要由调用方自己管理。— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
session/disposed
session/disposed 是 DeepSeek Harness 在会话销毁时发出的事件,workspace-changes 订阅它来删除 scratch 目录。进程崩溃或强退时该事件不会发出,清理也就不会发生。— https://github.com/deepseek-ai/deepseek-harness/discussions/10336
maxFileBytes
maxFileBytes 是 workspace-changes 在捕获文件内容时的单文件大小上限。它限制单个文件写入 captures 的体积,但目录总量仍会随捕获文件数量增长。— https://github.com/deepseek-ai/deepseek-harness/discussions/10336

来源