dsh-service-control

by lxp731

开发与运行时github收录于 08-21

DSH 服务启停控制:HTTP API 与 dshctl CLI 按 profile 启动/停止/重启/查看状态,重启由独立进程执行,附带 shell 补全。

HTTP API and dshctl CLI for managing the dsh service: start, stop, restart and check status per profile, with graceful detached restart and shell completions.

安装

dsh plugin --profile web add github:lxp731/agents-plugins#path:/dsh-service-control

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗

安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。

README

目录

DSH 服务启停控制插件:HTTP API 控制启停/重启/状态,附带独立 CLI dshctl(含 shell 补全)。无 Web UI 面板。

控制逻辑在进程外(scripts/control.sh),插件通过 HTTP 路由调用;重启/停止由独立延迟进程执行,不会卡死插件自身。

安装

# 从 npm 安装(推荐)
dsh plugin --profile web add dsh-service-control

# 备选:从 GitHub monorepo 子目录安装
dsh plugin --profile web add github:lxp731/agents-plugins#path:/dsh-service-control

# 本地开发安装(从仓库目录调试时)
# dsh plugin --profile web add "file:."

装完重启 web profile 生效(结束当前 dsh web / dsh --profile web 进程后重新启动)。

插件位于 agents-plugins monorepo 的 dsh-service-control/ 子目录,故从 GitHub 安装需用 #path: 指定子目录。

启用 CLI 与补全

插件自带 CLI dshctl,安装后执行一次 setup 即可:自动链接到 ~/.local/bin/ 并安装补全(zsh/bash/fish 按检测到的 shell 自动选),幂等可重复执行,不改写任何 shell rc。新开终端后补全生效:

dshctl setup

如果提示 dshctl: command not found(多为 ~/.local/bin 不在 PATH),直接用包内命令执行 setup 即可,或改用全局安装:

~/.dsh/profiles/web/node_modules/.bin/dshctl setup   # 包内命令(profile 安装)
npm install -g dsh-service-control                   # 全局安装(npm 全局 bin 默认在 PATH)

使用

HTTP API

端点 方法 说明
/dsh-health GET 探活
/dsh-service/status GET 状态 JSON {ok, running, pid, port, url, profile, note}(port/url 检测不到时为 null)
/dsh-service/start POST 后台启动(随后自动打开浏览器标签)
/dsh-service/stop POST 优雅停止(SIGINT,由独立进程执行)
/dsh-service/restart POST 延迟重启(独立进程执行,先休眠 3s 再重启)

CLI

dshctl start|up                 # 启动(就绪后自动打开浏览器)
dshctl stop|down                # 停止(systemctl stop,绝不自动重启)
dshctl restart|reload           # 重启
dshctl status|ps                # 状态(已 enable 时附带 [systemd 状态])
dshctl open                     # 浏览器打开服务页面
dshctl enable|on                # 创建 systemd unit(服务 + 看门狗)+ 开机自启
dshctl disable|off              # 取消自启、停看门狗并删除 unit 文件
dshctl probe|h                  # 探活 /dsh-health(可达性 + 延迟)
dshctl info|i                   # 概览(profile/unit/pid/端口/看门狗/版本)
dshctl doctor|d                 # 一键自检
dshctl logs|l dsh|journal [-f]   # 查看 dsh 日志文件 或 systemd journal(可 -f 跟随)
dshctl diagnostics              # 导出诊断包
dshctl config [get/set]         # 查看/设置持久化配置(如 DSH_WATCHDOG_FAIL_LIMIT)
dshctl setup                    # 启用 CLI + 安装补全
dshctl uninstall                # 移除 CLI 链接、补全与 systemd unit

支持 --profile <name>(默认 web;旧命令也支持 dshctl stop web 位置写法)。


## 开机自启与自愈(systemd user units)

`dshctl enable` 写入两个 unit 并 `systemctl --user enable`(均幂等):

| unit | 作用 |
|---|---|
| `dsh-<profile>.service` | 主服务:`dsh --profile <profile> --no-open`,`Restart=on-failure` + `RestartSec=10`,`KillSignal=SIGINT` |
| `dsh-<profile>-watchdog.service` | 看门狗:进程外每 3s 探测 `/dsh-health`,连续 3 次无响应(约 10s)→ `systemctl --user restart` 主服务 |

**退出原因由 systemd 判定,正常退出绝不重启:**

- 正常退出(退出码 0 / Ctrl+C 的 SIGINT / SIGTERM / `dshctl stop` / `systemctl stop`)→ **不重启**(systemd 视 SIGINT/SIGTERM/exit 0 为干净退出,`systemctl stop` 显式停止更永不触发重启)。
- 异常退出(非零退出码、崩溃信号如 SIGSEGV/SIGABRT/SIGKILL、OOM killer)→ **10s 后自动拉起**。
- 卡死(进程活着但 `/dsh-health` 无响应)→ 看门狗约 10s 后重启;正常停掉的服务 unit 为 inactive,看门狗绝不会碰它。

已 enable 后 `dshctl start/stop/restart/status` 自动走 `systemctl --user`(保证生命周期一致,避免手动 pkill 与 systemd 自动重启打架);未 enable 时仍是原始进程控制。`dshctl disable` 会先停掉看门狗,再取消自启并删除两个 unit 文件。

- 日志(两种):
  - **文件日志**(dsh 的 console + 插件的生命周期事件):`$HOME/.dsh/logs/dsh/YYYYMMDD-dsh-<profile>.log`(按日轮转;`dshctl config set DSH_LOG_DIR <dir>` 可改目录,`DSH_LOG` 可指定全路径)→ `dshctl logs dsh`。
  - **systemd journal**:`journalctl --user -u dsh-<profile>`、`journalctl --user -u dsh-<profile>-watchdog` → `dshctl logs journalctl`。
- 无 systemd 环境(容器/未启用 systemd 的 WSL)会报错;无图形会话的开机自启可先 `loginctl enable-linger`。
- enable 时若 dsh 正在 systemd 之外运行,会提示先 `dshctl stop` 再 `dshctl start` 迁入 systemd 托管。

## 配置

插件 Config 支持 `profile`:指定控制哪个 profile,默认取启动 dsh 时的 `--profile` 参数(否则 `web`)。在 profile 的 `cordis.patch.yml` 或 `--patch` overlay 中按 id 覆盖该行(`config` 为整体替换):

```yaml
- id: dsh-service-control
  config:
    profile: tui

测试

npm test        # 单元测试:插件形态 / Config / inject / patch 行
npm run smoke   # smoke test:隔离 profile 安装 → 组合配置断言 → 启动 → /dsh-health 探测(无 dsh CLI 时自动跳过)

卸载

dshctl uninstall             # ① 删 CLI 链接 + 三处补全 + systemd 开机自启 unit
dsh plugin --profile web remove dsh-service-control   # ② 移除插件本体(多 profile 逐一执行)
重启 web profile 生效        # ③ 结束当前 dsh web 进程后重新启动

dshctl uninstall 会扫描 ~/.config/systemd/user/,自动检测并删除 dshctl enable 创建的 unit(dsh-<profile>.service,含本插件模板签名;仅删除我们自己的文件,同名但非本插件的 unit 保留):先 systemctl --user disable,再删除文件并 daemon-reload。

可选残留:旧版 /tmp/dsh-web.log(新日志在 ~/.dsh/logs/dsh/)。

崩溃自动拉起需进程外机制(插件在进程死亡时无法自救),建议配合 systemd user service 使用。

原始 README: https://github.com/lxp731/agents-plugins/blob/main/dsh-service-control/README.md ↗