DSH 對 profile 配置保持熱監聽,新增或移除 bundle 會當場掛載,工具立刻可用。但 hmr 默認只監聽配置,不監聽源碼模塊,修改已經掛載的插件源碼不會生效,必須重啓。重啓 DSH 意味着當前瀏覽器連接斷開,如果重啓失敗,服務就再也起不來了。dsh-restart 把這件事做成一次工具調用,並保證兩件事:一是優雅退出,二是退出前確認“有人會把它拉起來”。
插件簡介¶
dsh-restart 是一個 DSH 插件,由 ajia1206 維護,採用 MIT 許可證。它爲正在運行的 DSH 進程提供一鍵重啓能力,具備 launchd 監管檢測、可覈驗的重啓日誌以及右下角 GUI 控件。
核心能力¶
優雅退出與託管檢測¶
插件探測自己是被誰託管的,再決定退出策略:
- Desktop 策略:識別爲 macOS 桌面版(有主進程與 IPC 連接),通過 macOS 應用退出/重新打開走一遍。
- Launchd 策略:本進程是該 launchctl job 的主進程,且 KeepAlive 是無條件開啓(條件式策略不認),則直接調用
ctx.appExit(0)優雅退出。 - Supervisor 策略:沒有可確認的 KeepAlive 託管(手動啓動、父進程不隨退出的情況),派 detached supervisor。它在被殺之前先寫記錄,並在恢復資源預檢通過後寫
supervisor-ready。插件必須等到這兩條齊全才允許自己退出,8 秒內沒等到就中止。 - None 策略:沒有託管且
superviseFallback=false,拒絕重啓。
可覈驗的重啓日誌¶
重啓日誌以 JSONL 格式記錄在 <home>/.dsh/logs/dsh-restart.log,以 0600 權限創建。關鍵記錄類型包括:
* boot:插件就緒時寫入,帶 pid/ppid/模式/端口/profile。
* armed:安排重啓時寫入,帶 armId、fireAt 與原因。
* supervisor / supervisor-ready:Supervisor 握手狀態。
* exiting / supervised:退出過程與拉起結果。
* cancelled / aborted:取消或中止狀態。
GUI 控件與鑑權¶
Web 界面右下角有一個懸浮的“↻ 重啓”按鈕,顯示託管方式、端口、停機時長,支持延遲選擇與原因填寫。控件落在 shell.overlay 座位上,點擊穿透。
鑑權方面,註冊路由本身不帶鑑權,但強制只接受迴環來源(127.0.0.0/8、::1、::ffff:127.x)。非迴環一律 403。這是爲了防止反向代理轉發的外部請求誤傷。
安裝¶
安裝前請檢查源碼與許可證。
dsh plugin --profile web add github:ajia1206/dsh-restart
典型用法¶
插件提供三個命令行工具和一個瀏覽器控件,共用同一套實現。
- dsh_restart [delaySeconds] [reason] [dryRun]
安排一次重啓。默認延遲 10 秒,爲了讓工具結果先送達瀏覽器。dryRun只看計劃不安排。 - dsh_restart_status
查看託管方式、當前是否已安排重啓、以及重啓歷史。這是覈驗手段,可計算停機時長。 - dsh_restart_cancel
在觸發前取消重啓。 - 瀏覽器右下角懸浮按鈕
點擊懸浮按鈕進行重啓,需經過確認彈窗。
配置¶
插件依賴 cordis.patch.yml 補丁,路徑配置需使用絕對路徑(不展開 ~ 或環境變量)。
- 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
注意事項¶
- 未發佈到 npm:
dsh-restart這個名字在 npm 上已被佔用,本包通過 GitHub Release 的 tgz 安裝。 - 絕對路徑:
logPath和childLogPath必須是絕對路徑,寫~會在當前目錄下創建名爲~的目錄。 - 鑑權說明:強制只接受迴環來源。如果宿主沒有 connection 服務,外部請求(即使是本機反向代理)也會被 403。
- 重複實例:Supervisor 無法證明沒有別人已經把它拉起來(launchd、手工操作等),因此可能存在兩個實例同時運行的情況。
- 權限:重啓日誌以 0600 創建,但 supervisor 的子進程日誌
childLogPath按系統默認權限創建。