dsh-restart
One-call restart for the running DSH process, with launchd-aware supervision detection, a verifiable restart log, and a bottom-right GUI control. 适合需要频繁重启DSH服务以应用配置或更新插件的开发与运维人员。
Other repositories with this package name
Install
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:ajia1206/dsh-restartREADME
Read the full README ↗配置
- id: dsh-restart
name: dsh-restart
config:
logPath: /绝对路径/.dsh/logs/dsh-restart.log
childLogPath: /绝对路径/.dsh/logs/dsh-restart-child.log
defaultDelaySeconds: 10
maxDelaySeconds: 600
superviseFallback: true
trustParentJob: false
healthUrl: ''
healthTimeoutMs: 60000
healthIntervalMs: 500
exitTimeoutMs: 45000
bootHistoryLimit: 5
路径必须是绝对路径:这两个值会被原样使用,不展开
~,也不展开环境变量。写~/.dsh/...会在当前工作目录下真的建一个名叫~的目录。不想手写路径就不要配这两项,用默认值——默认值由homedir()拼出来,是正确的。
| 字段 | 默认值 | 含义 |
|---|---|---|
| logPath | /.dsh/logs/dsh-restart.log | 重启记录(JSONL) |
| childLogPath | /.dsh/logs/dsh-restart-child.log | supervisor 拉起的新进程的 stdout/stderr |
| defaultDelaySeconds | 10 | 默认延迟秒数 |
| maxDelaySeconds | 600 | delaySeconds 上限 |
| superviseFallback | true | 无托管时是否派 supervisor 兜底 |
| trustParentJob | false | 见下方"launchd 与父进程" |
| healthUrl | 空 | 留空则用 --port 推导 http://127.0.0.1:/ |
| healthTimeoutMs | 60000 | supervisor 等端口恢复的上限 |
| healthIntervalMs | 500 | 健康检查轮询间隔 |
| exitTimeoutMs | 45000 | supervisor 等旧进程退出的上限;超时不强制终止任何进程,直接如实报失败 |
| bootHistoryLimit | 5 | 状态里保留的最近重启次数 |
端口是从 DSH 自己的 cmdlineArgs 里读 --port 得来的,不靠猜;读不到才退回 lsof。两者都拿不到且 healthUrl 为空时,拉起照常执行(这条路径上能阻止拉起的只有两件事:旧进程没退出、宿主没提交退出),只是「服务是否恢复」只能由新进程写的 boot 记录来确认,没有端口层面的证据。
launchd 与父进程
判断"launchd 会不会把我拉回来"时,只认两种情况之一:本进程就是某个 KeepAlive 任务的主进程(job.pid === pid),或者该任务的主进程是本进程的直接父进程(job.pid === ppid)。
只有第一种能证明 launchd 会重启我。第二种依赖一个额外假设——父进程会随本进程一起退出——而这个假设无法在本地证明:如果父进程是个不随子进程退出的包装进程,本进程退出后就没有任何人拉起它。
所以第二种默认不走 launchd,改用 supervisor 兜底(慢一点,但不会把自己关在门外)。只有你明确知道自己的父进程会随子进程退出时,才把 trustParentJob 打开;打开后 warning 仍会保留,因为那条链路上 KeepAlive 重启的毕竟是 job 主进程,比自持多两个不确定环节。
KeepAlive 的读法按这个原则收紧:只在 launchctl print 输出的 properties 里读,且支持它的两种真实渲染——本机(macOS 26)是单行旗标表 properties = keepalive | runatload | ...,列表里有 keepalive 才算无条件开启;旧式多行 properties = { keepalive = 1 } 块也认。不对整段输出做关键字匹配——否则 job label、环境变量值或 endpoint 名里出现 "keepalive" 就会被误判成有人托管。条件式策略(semaphores = { successful exit => 0 },或块里的字典值)一律不认;没有 properties 行时按"无法确认"处理,同样倒向 supervisor。