dsh-restart-control
為 DSH Web 提供跨平台、受控的「重啟 DSH」設定頁面。管理者可以在 Web UI 發出固定格式的重啟請求,插件會先保存狀態,再依主機環境選擇交由外部服務管理器重啟,或由內建的 portable helper 重新拉起 DSH。
[!WARNING] 若 DSH 已由 PM2、Docker、Windows Service、systemd 或其他服務管理器負責自動重啟,請使用
DSH_RESTART_CONTROL_MODE=external,避免外部管理器與 portable helper 同時拉起多個 DSH 進程。若 DSH 是在 Windows、macOS 或沒有服務管理器的 Linux 上手動啟動,預設的auto模式會使用跨平台 portable helper。
功能
- Web 設定頁: 在 DSH Web 的設定頁加入「重啟 DSH」區塊,提供確認、狀態顯示與重新整理按鈕。
- 跨平台重啟: 支援 Windows、macOS 及 Linux;沒有 systemd 或其他外部管理器時,可由內建 helper 重新拉起原本的 DSH 進程。
- 外部管理器整合: 在 systemd、PM2、Docker、Windows Service 等環境中,可只退出並返回固定的 exit code 75,讓既有管理器依其重啟策略接管。
- 受控重啟: 瀏覽器只提交
settings狀態,不接受 shell 命令、檔案路徑或服務管理器參數。 - 可靠確認: 宿主端先保存
scheduled狀態;新進程產生新的bootId後才會將狀態標記為success。 - 失敗可見: 請求逾期、時間格式錯誤、連續重啟過快、狀態保存失敗或 helper 無法啟動時,UI 會顯示失敗原因,不會偽報成功。
- 無需廣泛權限: 插件不要求為 DSH Web 授予 root、sudo、systemd 或 shell 執行權限。
重啟策略
插件讀取環境變數 DSH_RESTART_CONTROL_MODE。只接受下列固定值;未設定或填入未知值時會回到 auto:
| 值 | 行為 | 適用情境 |
|---|---|---|
auto(預設) |
Windows 直接使用 portable;macOS/Linux 偵測到 systemd 管理環境時使用 external,否則使用 portable。 | 手動啟動的 DSH,或希望由插件自動判斷的環境。 |
portable |
啟動內建 helper,等待目前 DSH 進程退出後,以原本的 Node executable、參數、工作目錄與環境重新拉起 DSH。 | Windows、macOS、沒有服務管理器的 Linux。 |
external |
保存 scheduled 後以 exit code 75 結束目前進程,不自行啟動子進程。 |
systemd、PM2、Docker、Windows Service 或其他已配置自動重啟的管理器。 |
systemd |
external 的相容別名。 |
舊版只使用 systemd 命名的部署設定。 |
auto 不會呼叫 systemctl 或其他服務管理命令;在非 Windows 環境只讀取 systemd 注入的 INVOCATION_ID、NOTIFY_SOCKET 或 SYSTEMD_EXEC_PID 來判斷是否交由外部管理器。若部署環境的偵測結果不符合預期,請明確設定 portable 或 external。
建議選擇
- Windows 本機手動啟動: 保持
auto,或明確設定為portable。 - macOS/Linux 手動啟動: 保持
auto;沒有 systemd 時會使用portable。 - systemd 服務: 保持
auto即可;插件偵測到 systemd 後會使用external。也可以明確設定external。 - PM2、Docker、Windows Service 或其他管理器: 明確設定
external,由原有管理器處理 exit code 75。 - 不要在同一個 DSH 進程同時使用 portable 與外部自動重啟: 否則可能產生重複進程。
設定環境變數
在 Windows PowerShell 7 中,先在同一個 PowerShell 工作階段設定,再使用原本的 DSH 啟動命令:
$env:DSH_RESTART_CONTROL_MODE = 'portable'
# 在此執行你原本的 DSH 啟動命令
若 DSH 由 Windows Service、PM2 或 Docker 啟動,請把 DSH_RESTART_CONTROL_MODE=external 加到該管理器的服務環境,而不是只在互動式 PowerShell 中設定。設定完成後,必須重啟 DSH,新的環境變數才會生效。
安全模型
插件把瀏覽器請求限制在 dsh-restart-control settings namespace,請求只包含下列固定狀態欄位:
| 欄位 | 用途 |
|---|---|
state |
idle、requested、scheduled、success 或 failed |
requestId |
識別單次重啟請求,只接受受限格式的字串 |
requestedAt |
判斷請求是否仍在 10 分鐘有效期內 |
scheduledAt、completedAt |
記錄排程與完成時間 |
bootId |
識別目前 DSH 進程,確認服務確實經歷了重啟 |
message |
顯示受控流程的結果或失敗原因 |
宿主端的處理順序如下:
- 驗證
state、requestId與requestedAt,拒絕不合法、過期或時間超前過多的請求。 - 以
scheduled狀態保存請求,讓前端在 DSH 暫時離線前取得可靠的排程記錄。 - 在
portable模式啟動本地 helper;在external模式不啟動子進程,只以 exit code 75 結束。 - portable helper 不使用 shell,會等待原本的 DSH 進程退出,再使用宿主在啟動時的 executable、參數、工作目錄與環境拉起新的 DSH。
- 新進程產生新的
bootId,讀到上一個scheduled請求後標記為success。 - Web UI 在服務短暫離線期間輪詢
settings.describe,只有在看到相同requestId、新的bootId與success時才顯示重啟成功。
瀏覽器提交的 payload 沒有 command、path、executable 或服務管理器參數欄位。插件不把使用者提供的內容拼接成命令列,也不執行 shell: true、exec 或 systemctl。
環境需求
- 已安裝 DSH Web,並使用
webprofile。 - DSH 執行環境提供下列 peer dependencies:
@deepseek-ai/cordis^4.0.1@deepseek-ai/dsh-settings0.1.0-rc.7@deepseek-ai/schemastery^3.18.1
- Web client 可使用 DSH Web 已提供的 React runtime。
- 若使用
external,外部服務管理器必須已配置在 DSH 退出後自動重啟。 - 若使用
portable,DSH 必須由可重複使用的 Node executable、參數與工作目錄啟動;插件會沿用目前進程的啟動資訊。
安裝
以下命令在 DSH 主機上執行。先將 GitHub repository clone 到本地插件目錄,再把該目錄加入 web profile。
Linux、macOS 或其他 Unix-like 環境
git clone https://github.com/darkchaox/dsh-restart-control.git /home/dsh/local-plugins/dsh-restart-control
dsh plugin --profile web add /home/dsh/local-plugins/dsh-restart-control
若 DSH 由 systemd 管理,完成插件安裝後可使用原本的服務管理命令重啟:
sudo systemctl restart deepseek-harness.service
systemd 環境可以保持 DSH_RESTART_CONTROL_MODE=auto;插件會依 systemd 注入的環境資訊選擇 external。如需明確設定,可在服務單元加入:
[Service]
Environment=DSH_RESTART_CONTROL_MODE=external
Windows PowerShell 7
以下範例使用 PowerShell 7;請把本地目錄替換為你的 DSH 插件目錄:
New-Item -ItemType Directory -Force -Path 'C:/dsh/local-plugins' | Out-Null
git clone https://github.com/darkchaox/dsh-restart-control.git 'C:/dsh/local-plugins/dsh-restart-control'
dsh plugin --profile web add 'C:/dsh/local-plugins/dsh-restart-control'
Windows 本機手動啟動 DSH 時,推薦使用預設的 auto,或在同一個 PowerShell 工作階段明確使用 portable:
$env:DSH_RESTART_CONTROL_MODE = 'portable'
# 執行你原本的 DSH 啟動命令
如果 DSH 已由 Windows Service 或其他 Windows 服務管理器啟動,請改用 external,並在該服務的環境設定中加入:
DSH_RESTART_CONTROL_MODE=external
不要在 Windows Service 已配置自動重啟時使用 portable;portable helper 與 Windows Service 可能同時拉起 DSH。
更新插件
Linux、macOS:
git -C /home/dsh/local-plugins/dsh-restart-control pull --ff-only
dsh plugin --profile web add /home/dsh/local-plugins/dsh-restart-control
Windows PowerShell 7:
git -C 'C:/dsh/local-plugins/dsh-restart-control' pull --ff-only
dsh plugin --profile web add 'C:/dsh/local-plugins/dsh-restart-control'
更新後請使用 DSH 原本的啟動方式重啟一次。重新整理 DSH Web 設定頁;若側欄沒有立即出現新項目,請使用 Ctrl + F5 清除舊的 client bundle cache。
使用方式
- 開啟 DSH Web 的設定頁。
- 找到「重啟 DSH」區塊,先按「重啟 DSH」。
- 確認目前所有 Web 連線會短暫中斷,再按「確認重啟」。
- 插件保存
scheduled狀態後,會依重啟模式退出或啟動 portable helper。 - 等待 DSH 重新連線。UI 會在最多 60 秒內輪詢服務狀態。
- 只有新的 DSH 進程完成啟動並回報新的
bootId,畫面才會顯示「重啟成功」。
重啟期間請不要重複提交請求。宿主端有 10 秒冷卻時間,用於避免連續重啟。
外部服務管理器設定
systemd
systemd 服務需要具備自動重啟策略,例如 Restart=on-failure。可先檢查:
systemctl show deepseek-harness.service --property=Restart
預期輸出:
Restart=on-failure
插件在 systemd 下使用 external,以 exit code 75 結束,讓 systemd 依服務單元設定重新拉起 DSH。若服務不是 systemd 啟動,請不要只套用 systemd 指令,改用對應的管理器日誌與重啟設定。
PM2、Docker、Windows Service
這些管理器都應使用 external。核心要求是:管理器要把 DSH 的 exit code 75 視為需要重新啟動的結束狀態。
Docker Compose 的環境設定可參考:
services:
dsh:
environment:
DSH_RESTART_CONTROL_MODE: external
restart: on-failure
PM2、Windows Service 或其他管理器請在其服務環境中設定 DSH_RESTART_CONTROL_MODE=external,並確認既有的「進程異常退出後重啟」策略已啟用。插件不會替你修改這些管理器的設定。
故障排查
畫面顯示「重啟超時」
這表示 Web UI 在 60 秒內沒有等到新的 DSH 進程。請先確認你使用的重啟模式:
- 手動啟動的 Windows、macOS 或 Linux:確認
DSH_RESTART_CONTROL_MODE是auto或portable,並確認原本的 DSH 啟動命令仍可正常執行。 - systemd、PM2、Docker、Windows Service 或其他管理器:確認設定為
external,且管理器確實會在 exit code 75 後重新啟動 DSH。 - 不要在外部管理器已經自動重啟時使用
portable,避免同時出現兩個 DSH 進程。
接著查看對應啟動程序的日誌:
- systemd:
journalctl -u deepseek-harness.service -n 100 --no-pager - Docker:查看容器 logs 及容器的 restart status。
- PM2:查看 PM2 process log 與 process status。
- Windows Service:查看 Windows Event Viewer 或該服務管理器的日誌。
- 手動啟動:查看啟動 DSH 的 PowerShell、終端機或程序日誌。
畫面顯示「重啟失敗」
常見原因包括:
- 請求超過 10 分鐘有效期,或
requestedAt不是有效的 ISO 8601 時間。 - 距離上次重啟不足 10 秒,觸發冷卻保護。
- DSH settings service 無法保存
scheduled或failed狀態。 - 上一個進程在保存
scheduled前就中斷,插件因此不會在新進程中自動重試。 - portable helper 無法啟動,或原本的 executable、參數、工作目錄已不再可用。
請先查看 UI 顯示的 message,再檢查 DSH 日誌與啟動程序設定。
Windows 出現重複進程
這通常表示 Windows Service 或其他管理器已負責自動重啟,但模式仍為 portable 或 auto。在服務管理器的環境設定中加入:
DSH_RESTART_CONTROL_MODE=external
然後停止重複的 DSH 進程,只保留一個由服務管理器管理的實例,再重新啟動服務。
設定頁沒有出現插件
請依序確認:
- 插件已加入
webprofile,而不是其他 profile。 dsh plugin --profile web add使用的是包含package.json與cordis.patch.yml的插件根目錄。- 已使用 DSH 原本的方式重新啟動 DSH。
- 瀏覽器已使用
Ctrl + F5重新載入 client bundle。 - DSH 日誌沒有顯示 peer dependency 或插件載入錯誤。
發布披露
此插件不把資料傳送到外部雲端,也不需要 API key、Token 或其他外部憑據。以下資訊與 package.json 的 disclosure 欄位保持一致:
- 雲端依賴: 否;
network為空陣列,插件不主動連線到外部端點。 - 離線模式: 是;插件只透過 DSH 自身的 settings 與 Web RPC 工作,不依賴外部網路服務。
- 憑據處理: 不讀取、儲存或寫入 API key、Token、密碼或其他秘密,也不會把秘密寫入日誌。
- 環境變數: 只讀取
DSH_RESTART_CONTROL_MODE,並把它限制在auto、portable、external及相容別名systemd。 - 進程權限: 重啟請求通過驗證且狀態保存成功後,插件以 exit code 75 結束自身進程;portable 模式另外啟動固定用途的
restart-helper。helper 只使用宿主提供的 executable、參數、工作目錄與環境,不使用 shell。 - 檔案系統: 插件不直接讀寫檔案;重啟狀態由 DSH settings service 持久化,helper 只負責等待與重新啟動進程。
- DSH settings: 只讀寫
dsh-restart-controlnamespace 的固定狀態欄位。 - 法域標籤: 未宣稱特定法域;本項不構成法律意見。
- 資料保留:
server;只保留重啟流程狀態,不保留使用者對話內容。狀態清理方式請參考「回滾」章節。
檔案結構
dsh-restart-control/
├── cordis.patch.yml # 將插件加入 web profile 的 Cordis patch
├── package.json # 插件 metadata、peer dependencies 與 disclosure
├── README.md # 本說明文件
└── src/
├── client.js # DSH Web 設定頁 bundle
├── host.mjs # DSH 宿主端狀態機與重啟策略
└── restart-helper.mjs # 跨平台 portable 重啟輔助程序
開發與驗證
本插件沒有額外的 build script;宿主端與 Web client 由 DSH 的插件載入流程直接使用。提交變更前,可以使用 Node.js 進行基本語法與打包檢查:
node --check .\src\host.mjs
node --check .\src\client.js
node --check .\src\restart-helper.mjs
npm pack --dry-run --json --ignore-scripts
也可以使用相同的 Node major version 啟動一個短暫測試進程,驗證 helper 會等待父進程退出後再拉起指定進程;不要直接對正在運行的正式 DSH 實例做重啟測試。
插件的 runtime dependencies 由 DSH 執行環境提供,請不要把 DSH 的設定檔、服務金鑰或本地主機資料提交到 repository。
回滾
移除插件後,請使用 DSH 原本的服務管理方式重啟:
dsh plugin --profile web remove dsh-restart-control
# 使用原本的 DSH 啟動命令或服務管理器重新啟動
Linux systemd 可使用:
sudo systemctl restart deepseek-harness.service
移除插件不會刪除其他 settings namespace。若要清理插件留下的狀態,請先確認不再需要重啟記錄,再由 DSH 設定頁或受控的設定檔維護流程移除 dsh-restart-control 分節。
許可證
本專案採用 MIT License。
No comments yet. Be the first to write one.