dsh-launch:把長駐服務交給獨立 broker 進程監督

前言

在 DSH 對話裏讓模型啓動一個 dev server,常遇到的問題是:對話回合一結束、會話一關閉,服務就沒了。根因在於 pwsh 的後臺任務(jobs)綁定在 owner 會話作用域上,會話或回合結束時,dsh-jobs-local 會取消歸屬任務——服務根本活不到下一輪。

dsh-launch 針對的就是這個問題:把服務交給一個獨立的 detached broker 進程監督,使服務在對話回合結束、會話關閉、甚至 DSH 自身重啓後繼續運行。下面介紹它的機制、功能與用法。

這是什麼

dsh-launch 是 Khellendros97 維護的 DSH 服務管理插件,MIT 許可,當前版本 0.2.0,要求 Node >= 20。監督機制參考了 omp 的 launch daemon broker。

核心思路分三步:

1、服務由 detached broker 進程以 detached + stdio 落盤 的方式拉起,stdio 直接寫入磁盤日誌;
2、broker 只做監督——日誌增量、pid 探活、就緒檢測、崩潰退避重啓——自身空閒即退;
3、DSH 下次啓動時重新拉起 broker,並按 pid 收養仍在運行的服務。

插件是單包發佈:Service 側邊欄 tab、broker、模型工具全部在同一包內;better-sidebar 只負責承載 tab(經其擴展 API 注入,better-sidebar 側無需任何改動)。

核心功能

模型工具

  • service_start:啓動長駐服務,必填 name + command,可選 cwd/title/logo/env/readyLog/readyPort/restart,等待就緒後返回;
  • service_stop / service_restart / service_list / service_logs:停止(整樹殺)/ 重啓 / 列舉 / 讀日誌尾。

就緒判定會先剝離 ANSI 轉義,再對端口做 IPv4/IPv6 雙棧探測。

Service tab(側邊欄)

側邊欄中以服務卡片展示標題、logo(可選,URL 或圖片路徑)、狀態徽標、PID、運行時長、重啓次數,支持啓動 / 停止 / 重啓 / 查看日誌。tab 可見時輪詢插件自有的 fenced /launch/api 路由。

沒有安裝 better-sidebar 時,插件以 headless 模式運行:工具可用,無 UI tab。

ctx.launch(cordis 服務)

供其他插件消費,提供 ping / list / start / stop / restart / describe / logs。

監督機制

每服務維護一個狀態機:starting→running→ready→stopping→exited/failed(開啓重啓且失敗時進入 restarting 退避)。重啓策略有 no / on-failure(默認)/ always 三種,退避爲指數遞增,從 1s 到 30s。

通信上,宿主與 broker 之間採用命名管道 NDJSON 協議 + token 認證,管道名按 runtimeDir 哈希,多部署不會衝突。

就緒檢測有兩個開關:

  • readyLog:輸出正則匹配,ANSI 轉義已剝離;
  • readyPort:TCP 探測,未指定 host 時同時探 127.0.0.1 與 ::1。

start/restart 等待就緒默認 20s,上限 60s。broker 重啓後收養 starting 記錄時,會重掃日誌尾部已滾過的就緒標記,避免誤判。

Windows 上,command 字符串服務經 cmd.exe /d /c 由內置 node 啓動器(broker/launcher.cjs)執行——detached 的 cmd 會丟失批處理子進程輸出,啓動器規避了該問題;整樹停止用 taskkill /T。

安裝與啓用

前置條件:DSH web 環境;dsh-better-sidebar 是可選依賴(^0.11.0 || ^0.12.0),僅 UI 需要。

dsh plugin --profile web add dsh-launch

一條命令完成安裝 + 自動掛載:包內 cordis.patch.yml 會註冊進 dsh.profile.bundles。裝完先重啓 dsh web,再硬刷新瀏覽器(Cmd/Ctrl+Shift+R)。

配置

插件行可選 config,共有三個配置項:

- id: dsh-launch
  name: dsh-launch
  config:
    runtimeDir: '~/.dsh/tmp/dsh-launch'   # 運行時目錄,默認同左
    idleGraceMs: 15000                     # 無客戶端/無 presence 後的退出寬限
    maxLogBytes: 8388608                   # 單服務日誌輪轉閾值,8MB

運行時目錄 ~/.dsh/tmp/dsh-launch/ 下包含:broker.token、broker.pid(單實例租約)、presence/*.json(DSH 存活標記)、daemons/<name>/(元數據 + 日誌,8MB 輪轉)。

測試

npm test

測試分兩部分:broker 冒煙 15 項(啓動、就緒含 ANSI 與 IPv6、日誌、停止、重啓、持久化、殺 broker 後收養、收養尾部重掃)與接線 13 項(服務提供 / 工具註冊 / presence / 真實 broker 往返 / fenced 路由信封 / 圍欄拒絕 / 客戶端契約)。

安全說明

  • 服務以運行 DSH 的同一用戶身份、脫離任何沙箱執行——這是服務存活的前提,服務等同於用戶在終端啓動的進程;
  • /launch/api 與 /launch/service-logo 全部經 Host 頭信任圍欄(loopback 或 trustedHosts);broker 管道僅綁定本機(命名管道 + token);
  • 插件卸載(HMR/禁用)不會停止服務或 broker;broker 在無 presence 且空閒 15s 後自行退出,服務繼續運行。

限制

  • 服務名全局唯一(全機一個 broker 作用域);
  • 無 PTY / 無 stdin:交互式進程請改用 better-sidebar 終端;
  • broker 死亡窗口內(DSH 未運行且 broker 已退出)崩潰的服務不會自動重啓,detached 服務本身不受影響。

適用場景與注意

適合的場景:dev server、watcher、mock API、worker 這類需要跨回合、跨會話存活的進程。只要流程裏有「模型起了個服務,下一輪還要用」,這個插件就把服務生命週期從對話生命週期裏解耦出來。

注意兩點:插件以當前 dsh 進程權限運行,服務也以同一用戶身份、脫離沙箱執行;安裝前建議自行檢查源碼與許可證(MIT)。

結尾

回顧一下:dsh-launch 用一個 detached broker 進程解決後臺服務隨會話回收的問題,服務在回合結束、會話關閉、DSH 重啓後都能繼續運行,同時提供模型工具、側邊欄 UI 和跨插件 API 三套入口。DSH 的理念是「一切皆插件」,這類把基礎設施問題封裝成插件的思路,值得在搭建自己的工作流時參考。

  • GitHub:https://github.com/Khellendros97/dsh-launch
  • 社區目錄頁:https://www.skillhub.cn/plugins/Khellendros97/dsh-launch (社區站點,與 DeepSeek / 幻方無官方從屬關係)
羽毛球分组比赛记分
小程序二维码

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

小夜