我現在安裝 Windows 服務都使用功能完整的 nssm 來管理,他除了有 CLI 命令列工具介面外,也同時有支援 GUI 圖形化介面,所以非常容易上手。今天這篇文章我打算來分享幾個常見的用法。
以下命令皆使用 Command Prompt (命令提示字元) (cmd.exe
) 來執行。
關於 nssm
服務管理員
Windows 內建的各種註冊 Windows 服務的工具都非常難用(sc.exe),不然就是功能太過陽春(New-Service),而且這些工具沒辦法幫你處理一些程式出錯的狀況,所有例外你都要在自己的程式處理,簡單來說,就是爛 (Sucks
)! ?
所以 nssm
出現了,這個名字非常諷刺,這四個字就是 Non-Sucking Service Manager 的意思! ?
nssm
會額外幫你監控服務執行的狀況,如果發生「異常例外」導致程式掛掉,程式自動重啟。即便程式寫成異常發生但「正常結束」,最後 Windows 服務管理員還是會幫你自動重啟。
使用 nssm
安裝並啟動 Windows 服務
-
安裝 nssm
工具
常看我文章的朋友應該都知道,我都是用 Chocolatey 來安裝軟體:
choco install nssm -y
事實上 nssm
是免安裝的綠色軟體,而且只有 nssm.exe
單一執行就可以運行。只要從 官網下載 壓縮檔回來,將 nssm.exe
解壓縮到 C:\Windows
底下就直接可以用了!
注意: 使用 nssm
註冊服務時,它會自動在你的 事件記錄器 中註冊一個 名為 NSSM
的 事件來源 (Event Source)。
-
使用 GUI 介面安裝 Windows 服務
請以系統管理員身份執行 Command Prompt (cmd.exe
),並使用以下命令執行安裝:
nssm install MyService
這個命令事實上會自動開啟 nssm
的 GUI 圖形化介面,非常容易上手好操作:
設定好之後,按下 Install service 就會自動安裝成功!?
如果要移除 Windows 服務,也可以這樣執行,也一樣會跳出 GUI 介面:
nssm remove MyService
-
使用 CLI 介面安裝 Windows 服務
以下就是一個最簡單的「免互動」安裝 Windows 服務命令:
nssm install MyService "C:\EC.Services\訂單處理服務.exe"
他會自動幫你設定應用程式路徑(Application
)、工作目錄(AppDirectory
)等參數,如果你的程式可以這樣執行,不需要其他應用程式殼層(AppShell),例如 dotnet.exe
或 java.exe
等等。那麼,這確實是最簡單的建立服務方法。
以下是「免互動」重新啟動 Windows 服務命令:
nssm stop MyService
nssm start MyService
nssm restart MyService
以下是「免互動」移除安裝 Windows 服務命令:
nssm remove MyService confirm
-
使用 CLI 介面安裝需要有 應用程式殼層 (AppShell) 才能啟動的 Windows 服務
這邊我說的是像 dotnet.exe
或 java.exe
這種類型的應用程式,.NET Core 就需要 dotnet.exe MyService.dll
來啟動,而 Java 的 *.jar
就需要執行 java.exe -jar MyService.jar
才能啟動這種。
這種類型的應用程式,第一次透過 nssm
註冊服務的人,會很容易忘記設定 AppDirectory
(工作目錄) 參數,導致應用程式很容易會啟動失敗!
以下就是一個完整的範例,從安裝服務、設定參數到自動啟動,一口氣設定到好:
解释
nssm install MyService "C:\Program Files\Zulu\zulu-8\bin\java.exe" nssm set MyService AppDirectory "C:\Projects\MyService\target" nssm set MyService AppParameters "-jar MyService-0.0.1-SNAPSHOT.jar --server.port=8080" nssm set MyService AppStdout "C:\Projects\MyService\target\MyService-0.0.1-SNAPSHOT.log" nssm start MyService
認識 nssm
的服務執行參數
nssm
提供非常大量的參數可供設定,我也趁著這篇文章全部閱讀過一遍,這才發現 nssm
真的非常強大,果然是我心目中的王者!
以下我列出所有的服務執行參數,這些參數都可以對應到 nssm
的 GUI 圖形化介面上的頁籤,我會額外加上註解說明用途與預設值,詳細說明請見 NSSM Usage 文件!
你可以透過以下命令查詢 nssm
實際註冊到 Windows 服務之後的 nssm
服務執行參數為何。
注意「雙引號」傳遞應用程式參數可能造成的問題
在 Command Prompt 命令提示字元中,一直以來最被詬病的問題,就是「雙引號」的跳脫處理會讓整個命令變的可讀性極差,所以當你需要傳遞參數到服務應用程式時,需要傳入執行的參數包含「雙引號」,那就有地方要特別注意了!
假設你的應用程式參數必須包含空白字元,所以需要使用雙引號框起來:
-
手動執行的寫法
"C:\EC.Services\訂單處理服務.exe" "This is one argument"
-
使用 nssm
的安裝命令
nssm install "訂單處理服務" "C:\EC.Services\訂單處理服務.exe" """This is one argument"""
假設你要執行 Java 應用程式,參數可能很複雜,例如:
-
手動執行的寫法
REM 設定 JavaExe 變數不需要加上雙引號
JavaExe=C:\Program Files\Zulu\zulu-8\bin\java.exe
"%JavaExe%" -Dsolr.solr.home="%CD%\solr" -Djetty.home="%CD%" -Djetty.logs="%CD%\logs" -cp "%CD%\lib\*.jar";"%CD%\start.jar" -jar "%CD%\start.jar"
使用 %CD%
可以取得當前目錄的路徑!
-
使用 nssm
的安裝命令
REM 設定 JavaExe 變數不需要加上雙引號
JavaExe=C:\Program Files\Zulu\zulu-8\bin\java.exe
nssm install solr "%JavaExe%" -Dsolr.solr.home="\"%CD%\solr"\" -Djetty.home="\"%CD%"\" -Djetty.logs="\"%CD%\logs"\" -cp "\"%CD%\lib\*.jar"\";"\"%CD%\start.jar"\" -jar "\"%CD%\start.jar"\"
你看看,這段批次檔多醜啊! ?
注意設定環境變數的寫法
在服務啟動之前設定好環境變數,這應該是我最愛 nssm
的功能之一了!
架設我希望在執行 MyService
服務之前,先給定三個環境變數,分別是 A=1
, B=2
, C=3
等等,那麼你應該在建立好服務且尚未啟動服務之前,先這樣設定好環境變數:
nssm set MyService AppEnvironmentExtra "A=1" "B=2" "C=3"