宿主崩溃后自动诊断修复并推送告警
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/FoolishWiser/dsh-restart-guard.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令发起外部网络请求
查看扫描证据(共 14 处,展示前 14 条)
- 执行外部命令来自配置/变量lib/index.js:254
const child = spawn(process.execPath, args, { - 发起网络请求lib/client.js:266
const response = await fetch(`api/restart-guard/${path}`, { - 发起网络请求lib/shared/probe.js:45
req = transport.request( - 执行外部命令固定命令lib/shared/probe.js:211
const ps = spawnSync('ps', ['-o', 'command=', '-p', String(pid)], { encoding: 'utf8', timeout: 3000 }) - 执行外部命令固定命令lib/shared/probe.js:289
const ps = spawnSync('ps', ['-axo', 'pid=,command='], { encoding: 'utf8', timeout: 5000 }) - 执行外部命令固定命令lib/shared/probe.js:391
const lsof = spawnSync('lsof', ['-nP', `-iTCP:${port}`, '-sTCP:LISTEN', '-t'], { encoding: 'utf8', timeout: 4000 }) - 执行外部命令来自配置/变量lib/shared/probe.js:418
const probe = spawnSync(process.platform === 'win32' ? 'where' : 'which', [command], { encoding: 'utf8', timeout: 3000 }) - 执行外部命令来自配置/变量lib/shared/maintenance.js:339
return execFileSync(command, args, { encoding: 'utf8', timeout: 10000, stdio: ['ignore', 'pipe', 'pipe'] }) - 执行外部命令来自配置/变量lib/repair.js:62
child = spawn(spec.nodePath || process.execPath, argv.slice(1), { - 执行外部命令来自配置/变量lib/repair.js:283
const result = spawnSync(node, [bin, '--profile', profile, '--dump-config'], { - 执行外部命令来自配置/变量lib/repair.js:459
const result = spawnSync(process.execPath, ['--check', abs], { encoding: 'utf8', timeout: 20000 }) - 发起网络请求lib/shared/notify.js:251
const response = await fetch(target, { - 执行外部命令来自配置/变量lib/shared/notify.js:285
child = spawn(program, args ?? [], { stdio: ['pipe', 'ignore', 'pipe'], timeout: 15000, shell: false }) - 执行外部命令来自配置/变量lib/install.mjs:106
const result = spawnSync(pnpm, ['install'], {
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成dsh-restart-guard · 重启守护
English · 简体中文
给 DeepSeek Harness 的 Web 服务加一个守护进程,宿主进程死掉后它还能继续存活:发现重启没起来,按一组小规则判断原因,能修的自己修,修不了就把过程和结论发到你指定的渠道(IM、Webhook、命令或本地日志)。
它解决的问题很具体:容器/脚本里 dsh web 是后台启动,启动器随后 exec 成代理,插件加载失败、patch 写坏、端口被占时,没有任何 supervisor 会把服务拉起来。页面 502 到有人发现为止,中间没有任何信息。
DSH 宿主 (dsh web) 独立 watcher ┌───────────────────────┐ spawn ┌──────────────────────────────┐ │ 插件:体检 / 路由 / │ ─────────► │ 每 2s 探测 127.0.0.1:<port>/ │ │ 设置页 │ │ 字节偏移确认就绪 → 诊断 → 修复 │ │ │ ◄───────── │ → 通知 │ └───────────────────────┘ state.json└──────────────────────────────┘ │ 崩溃 / 被杀 │ ▼ ▼ 端口消失 ─────────────────────────►
展开完整文档(README 剩余 1 节)
dsh-restart-guard · 重启守护
English · 简体中文
给 DeepSeek Harness 的 Web 服务加一个守护进程,宿主进程死掉后它还能继续存活:发现重启没起来,按一组小规则判断原因,能修的自己修,修不了就把过程和结论发到你指定的渠道(IM、Webhook、命令或本地日志)。
它解决的问题很具体:容器/脚本里 dsh web 是后台启动,启动器随后 exec 成代理,插件加载失败、patch 写坏、端口被占时,没有任何 supervisor 会把服务拉起来。页面 502 到有人发现为止,中间没有任何信息。
DSH 宿主 (dsh web) 独立 watcher ┌───────────────────────┐ spawn ┌──────────────────────────────┐ │ 插件:体检 / 路由 / │ ─────────► │ 每 2s 探测 127.0.0.1:<port>/ │ │ 设置页 │ │ 字节偏移确认就绪 → 诊断 → 修复 │ │ │ ◄───────── │ → 通知 │ └───────────────────────┘ state.json└──────────────────────────────┘ │ 崩溃 / 被杀 │ ▼ ▼ 端口消失 ─────────────────────────► 重启 / 回滚 patch / 停下并告警
能力
- 活得比宿主久:watcher 由插件以 detached 方式拉起,和 DSH 没有父子关系;kill -9 DSH 不会带走它。
- 知道什么叫「起来了」:401 且正文是 DSH 的鉴权文案,或 200 且含 __DSH_BOOT__ 才算 DSH;普通的 200 HTML 是陌生监听者,既不算健康,也绝不会被当成 DSH 杀掉。
- 只认新进程的新日志:就绪判定读取本次 spawn 之后追加的字节,必须出现带 token 的 dsh web: 访问行,再 settle 复验。整文件 grep 会命中旧行、拿到旧 token,这里刻意不做。
- 有边界的修复阶梯:用抓到的 argv/env/cwd 重启;把 cordis.patch.yml 回滚到能通过 --dump-config 的最新备份;或者停下并把证据交给人。每个事件最多启动 2 次;10 分钟 3 次崩溃进入 30 分钟暂停,避免重启风暴。
- 升级/维护期免误判:显式维护窗口、包树 inode/版本变化、<pkgRoot>.prev- 等兄弟目录、包管理器进程、$DSH_HOME/upgrade 最新目录、慢启动六路信号任一命中即进入维护态:不启动、不回滚、不杀进程。
- 尊重主动停止:宿主 exit(0) 被当作「操作者有意停的」,不拉起。
- 通知到你所在的地方:本地日志恒开;Webhook(飞书、企业微信、钉钉、Slack、Telegram、Discord、ntfy、healthchecks、通用 JSON);任意命令(argv 直传、消息走 stdin);dsh-im 插件(宿主不在线时先落盘,回来后补发)。设置页点「扫描 dsh-im」可直接从已装插件里列出 bot 与 target,不用手抄 ID。
- 装完就告诉你环境缺什么:设置页顶部有体检卡(启动日志、patch 备份、Webhook/IM、监督者、维护态),每个缺口都给出可操作提示;另有一键「模拟崩溃」演练(守护自己造成的停机不会被当成「卡死」,会直接重启)。
- 可选 AI 辅助判定:规则确实没有安全动作时才征询模型,模型只能选「重试 / 回滚 patch / 等待 / 人工」,不会执行任何命令(详见下文)。
安装
1. 本地目录或 npm 包
cd /path/to/dsh-restart-guard
pnpm install --ignore-scripts
2. 链接进 profile(会备份 package.json 并跑 pnpm install)
npx dsh-restart-guard install --profile web
或:dsh plugin --profile web add dsh-restart-guard 然后手动把 "dsh-restart-guard" 加进 profiles/web/package.json 的 dsh.profile.bundles
3. 重启 DSH,让插件加载(watcher 随宿主启动)
重启后打开 设置 → 重启守护:顶部体检报告会列出还缺什么(Webhook 地址、IM 的 botId/targetId、启动日志路径……),在页面里补完,点 测试通知。
命令行核对:
dsh-restart-guard status # watcher / 阶段 / 最近健康状态 dsh-restart-guard doctor # 与设置页同一套体检 dsh-restart-guard logs -f # 跟随守护日志
环境要求
| 项 | 要求 |
| Node | ≥ 22 |
| DSH | ≥ 0.2.1(用到 host 插件 API 与 webServer.tapIndex) |
| 系统 | Linux 完整支持(依赖 /proc);macOS 可用探测与监督逻辑,进程/端口映射回退到 lsof |
| 运行时依赖 | 无 |
升级 DSH 时
照常升级即可。升级脚本通常会杀掉旧进程、换树、再拉起;watcher 能从换树/兄弟目录/升级目录/包管理器进程/restarter 进程识别出「这是维护」,只观察、不抢端口、不中途回滚文件。维护窗口是锚定的:同一信号沿用原截止时间,不会因为进程还在而每 2 秒往后顺延;每个窗口只通知一次(信号变化才再发),显式窗口(maintenance start --minutes N)严格按 N 分钟结束、不额外加 graceMs。
修复判定
探测失败 → 宽限 → 诊断 → 计划:
| 诊断(先匹配者优先) | 日志示例 | 动作 |
| yaml-config | YAMLException、bad indentation | 回滚到最新可用备份,再启动 |
| patch-incompatible | cannot get property "webRuntime" without inject | 首次回滚,之后仅重启 |
| wildcard-host | host "0.0.0.0" is an unspecified (wildcard) address | 停下,需改配置 |
| port-in-use | EADDRINUSE | 端口被占:停下(开启 killStaleDshHolder 时只清理旧 DSH) |
| module-missing | Cannot find module | 停下,依赖缺失 |
| permission-disk-memory | EACCES、ENOSPC、ENOMEM | 停下,环境问题 |
| crash | Segmentation fault、Killed | 重启 |
| startup-failed / plugin-failed | entries did not activate、failed to apply loader entry | 重启 |
| stalled | 进程在、端口静默超过 stalledExitMs | 杀掉僵死进程再启动 |
| timeout | 超时未就绪 | 重启 |
| unknown | 其它 | 重启 |
每个事件都会写 incidents/.json、ALERT.md、一行日志,并按配置发通知。不自动修复的情形:非 DSH 进程占着端口、维护窗口内、包树不完整、通配地址绑定、缺模块、权限/磁盘问题、以及开启尊重主动停止时的 exit(0)。
AI 修复(可选,默认关闭)
开启后守护多一档修复手段,分两种模式:
- act(默认)· 完全权限:一旦判定服务起不来,先让 AI 直接处理——提示词里附带当前环境(端口、宿主 pid/运行时长、node 与 DSH 版本、profile 路径、cordis.patch.yml 及最近备份、启动日志路径与大小、端口监听者、诊断与证据、/proc 抓到的启动命令),再附上脱敏后的日志尾部;AI 可以读文件、改配置、补依赖、回滚 patch、重启服务,随后守护复验端口。先试 dsh 本体(dsh --profile headless "<prompt>",继承 DSH 自己的模型凭据与工具权限),再试插件直连(HTTP / 桥接);两者都不行才回退到原来的规则阶梯(重启 → 回滚 → 人工)。
- advise · 只判定:不给动作权限,只回一个 JSON 判定(retry/rollback-patch/wait/manual),映射到已有白名单动作;模型输出永远不会被当作命令执行。
坏插件可以直接修文件:当启动失败是某个第三方插件引起时(DSH 打印 startup failed / Failed plugins,但进程不退出、端口仍回 401),守护会从日志里解析失败条目与包名,把该包的 package.json、入口文件和根目录配置交给 AI,并要求它返回 fix-plugin(1–3 个文件的完整内容)。守护负责校验(路径必须在包内、≤64 KiB、无符号链接)、备份(原文件旁 .guard-bak-<时间>)、语法检查(node --check / JSON.parse)后再启动;任一步失败就全部还原。只有修不了时才退回 disable-plugin(禁用对应加载器条目)或 manual。核心包(@deepseek-ai/* 与本插件)永远不允许被 AI 修改;修好之后设置页会显示「AI 修复中」,可用 恢复 AI 修复 一键还原。
安全边界:维护窗口、包树不完整、有真正的监督者(systemd/pm2)时 AI 也不会动手;发送的日志已脱敏,环境变量只发键名,密钥与访问令牌不外发;不开启就没有任何外发。硬停与「非 DSH 进程占端口」同样不会被覆盖。
在 设置 → 重启守护 → AI 修复 里开启,选择模式与尝试顺序(dsh-agent-first / direct-first / dsh-agent-only / direct-only),再配服务商与密钥来源。密钥默认直接借用 DSH 自己的:读 $DSH_HOME/.credentials.yaml 的 refs: 块(DEEPSEEK_API_KEY、XIAOMI_API_KEY、OPENAI_API_KEY、ANTHROPIC_API_KEY),所以即使 dsh web 本身起不来,AI 修复仍然可用;也可改成只读环境变量(ai.credentialSource: "env")、只读 DSH 凭据库("dsh")或指定凭据名(ai.keyRef)。密钥只读、不写配置、不落日志。
ai.dshAgent 控制「dsh 本体」通道(command 默认 dsh、args 默认 ["headless"]、timeoutMs 默认 300000)。不想让守护直接连 API 时开桥接(ai.bridge):提示词写程序 stdin、判定从 stdout 读。点 测试 AI 验证链路,命令行等价命令 dsh-restart-guard ai-test。
配置
全局文件:$DSH_HOME/restart-guard/config.json(0600)。设置页可改,watcher 自动重载。
{
"enabled": true,
"locale": "auto",
"watchdog": {
"probeIntervalMs": 2000,
"probeTimeoutMs": 3000,
"startupGraceMs": 30000,
"bootTimeoutMs": 120000,
"settleMs": 5000,
"stalledExitMs": 20000,
"maxRestartAttempts": 2,
"rollbackProfilePatch": true,
"killStaleDshHolder": false,
"respectIntentionalStop": true,
"crashLoop": { "windowMs": 600000, "maxIncidents": 3, "pauseMs": 1800000 }
},
"maintenance": { "autoDetect": true, "graceMs": 900000, "lookbackMs": 1800000 },
"logs": { "bootLogPath": "", "mirrorToHostLog": true },
"ai": {
"enabled": false, "preset": "deepseek", "endpoint": "", "model": "",
"keyEnv": "DEEPSEEK_API_KEY", "keyRef": "", "credentialSource": "auto",
"bridge": { "enabled": false, "program": "", "args": [] }
},
"notify": {
"webhook": { "enabled": false, "preset": "generic", "url": "" },
"command": { "enabled": false, "program": "", "args": [] },
"im": { "enabled": false, "botId": "", "targetId": "", "format": "markdown" }
},
"supervision": { "mode": "auto" },
"security": { "allowRemoteMutations": false, "dangerousActions": false }
}
bootLogPath 通常不需要:宿主健康时守护会从 /proc/<pid>/fd/1 抓真实 stdout。若启动器把 stdout 接成管道,再手动指定。
logs.mirrorToHostLog(默认 true):守护把自己的日志行以 [dsh-restart-guard] 前缀追加进宿主的 stdout(即 bootLogPath 或抓到的 stdout 文件),所以容器部署时 docker logs <container> 里能直接看到「谁在修、修到哪一步」,不必再进容器翻 $DSH_HOME/restart-guard/。它只写这一行前缀,不会伪造 DSH 自己的访问行,就绪判定不受影响。
supervision.mode 决定「谁负责重启」:auto(默认)识别 systemd、pm2、supervisord 和容器;none 表示没有别的程序会重启 DSH,让守护照常动手(适合 CI,或 PID 1 是 systemd 但平台并不会重启服务的容器);supervised 表示只报告、不动手,用于检测不到真正归属者的场景。
- 状态目录 $DSH_HOME/restart-guard/ 必须能跨重启保留。
- 已有 systemd/pm2 等 supervisor 时,守护只报告,不与 supervisor 抢端口。
- 容器启动器自己会重启 DSH 时,守护在仲裁阶段看到端口恢复就等待,不会起第二个服务。
通知渠道
| 渠道 | 配置 | 说明 |
| 日志 | 恒开 | .../instances/<profile>-<port>/restart-guard.log,5 MB 轮转、保留 2 份 |
| Webhook | notify.webhook 或 DSH_RESTART_GUARD_WEBHOOK_URL | 预设:feishu、wecom、dingtalk、slack、telegram、discord、ntfy、healthchecks、generic |
| 命令 | notify.command | argv 直传(不经过 shell),消息写 stdin |
| IM | notify.im 或环境变量 | 需要 dsh-im 插件;发不出去先落 outbox,宿主回来后补发 |
消息按事件节流(60 秒),默认附 40 行日志尾部,token/cookie 已脱敏;除非显式开启,不含启动 token 与访问地址。
命令行
dsh-restart-guard status [--json] watcher/阶段/健康摘要 dsh-restart-guard doctor 环境体检 + 提示 dsh-restart-guard logs [-f] [-n N] 守护日志 dsh-restart-guard incidents 最近事件 dsh-restart-guard outbox 待补发的 IM 消息 dsh-restart-guard restart|start|rollback|simulate-crash dsh-restart-guard pause --minutes 30 暂停自动修复 dsh-restart-guard resume dsh-restart-guard maintenance start|end [--minutes 60] [--reason upgrade] dsh-restart-guard notify-test 发测试消息 dsh-restart-guard ai-test 征询一次 AI 判定(不执行动作)
复现坏插件演示(隔离端口 3098,不动线上 3079): bash demo/run.sh # 离线确定性:stub AI 通过 bridge 返回 fix-plugin demo/run.sh --real # 用 DSH 自己的凭据调真实模型 demo/run.sh --keep # 保留演示实例,用 demo/stop.sh 收尾
演示会把一个真实的第三方插件注册到 required 加载器 id 上,插件读取自己的 demo-config.json(enabled: false 时抛错),然后杀掉宿主。守护应当检测到「端口有 401 但启动失败」、杀掉半启动进程、调用 AI、把 enabled 改回 true、再启动成功。
dsh-restart-guard reload 重载配置 dsh-restart-guard install|uninstall [--profile web] [--dry-run] dsh-restart-guard purge 清空全部守护状态
命令行通过控制文件与 watcher 通信(不需要页面 token);动作需要存活 watcher,否则退出码 3。
安全与隐私
- 无遥测。没配渠道就是零外连;AI 默认关闭。
- 设置页 API 使用注入到页面壳里的每页 token;变更只接受 POST、动作白名单、请求体 ≤64 KB;远程变更默认拒绝(security.allowRemoteMutations)。
- 日志与通知在落盘/外发前脱敏(Webhook URL、IM id、token、cookie、Authorization、常见密钥字段);环境变量只存键名,不存值。
- 数据在 $DSH_HOME/restart-guard/:目录 0700、配置与计划 0600;写入不跟随符号链接。
细节见 SECURITY.md、PRIVACY.md。
排障
| 现象 | 检查 |
| 没有 watcher | dsh-restart-guard status;宿主启动后 10 秒内会拉起,插件日志里有 watcher-spawn |
| 端口起来了但守护没反应 | 体检里的 boot-log:没抓到 stdout 时仍能靠 HTTP 判定,但无法确认新 token |
| 不重启 | 状态是 maintenance/supervised:升级期和 systemd 下这是预期行为 |
| 反复重启 | state 文件里有诊断;修好后 resume |
| IM 没动静 | 先从 设置 → IM Bot 复制 botId/targetId,用「测试通知」验证 |
QQ 机器人只暴露 Bot ID:targetId 可以留空,守护会在该 bot 只有一个投递目标时自动使用它;还没有目标时,先和机器人私聊一次(或拉进群),再到 dsh-im 里「新建目标」,然后回到设置页重新扫描。
更多见 docs/TROUBLESHOOTING.md。
开发
pnpm install --ignore-scripts
pnpm run typecheck # tsc --noEmit,无构建步骤
pnpm test # node:test,含针对假 dsh 的 e2e
pnpm run build:client # 由 src/client.jsx 重新生成 lib/client.js
node scripts/build-client.mjs --check # CI:bundle 已提交且是最新
架构与不变量见 docs/ARCHITECTURE.md。
许可证
MIT,见 LICENSE。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
FoolishWiser/dsh-restart-guard
宿主崩溃后自动诊断修复并推送告警
相关插件 · 工具 / 效率
破甲管控台kingcharleslzy-ai/dsh-purge
dsh-purge Community · DeepSeek Harness 社区维护版:宿主兼容、状态诊断、提示词管理、更新与本机备份回滚。基于小杨 / YuJunZhiXue 的 dsh-purge。
★ 4,173已汉化DeepSeek 客户端
74.4
网文长卷lingfengQAQ/webnovel-writer
基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200…
★ 7,636已汉化DSH
72.2
多智能体协作HKUDS/AutoSwarm
AutoSwarm: Unify Your Agents. Unify Your Context (Codex · Claude Code · DeepSeek Harness · Muse · Grok · WorkBuddy· nanobot · and more)
★ 2,349已汉化DSH
71.6
Vox 拼贴视频生成Alisa0808/vox-director
🎬 Vox Director拼贴动效导演
★ 2,129已汉化DSH
71.4
Agent 演化引擎Q00/ouroboros
智能体 OS:智能体自己变聪明,我们只守住底线:面试准入、分阶段评估、带预算的进化循环。MCP 服务器,14 种运行时:Claude Code、Codex CLI、Gemini CLI、OpenCode、Copilot、Kiro 等。
★ 6,308已汉化DSH
71.3
智能体运行框架路由HarnessRouter/harnessrouter
智能体运行框架的统一接口。
★ 3,897已汉化DSH
71.2
这是你的仓库?认领条目