介紹好用工具:優異的 nssm 服務管理員 (Non-Sucking Service Manager)

我現在安裝 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 服務

  1. 安裝 nssm 工具

    常看我文章的朋友應該都知道,我都是用 Chocolatey 來安裝軟體:

    choco install nssm -y
    

    事實上 nssm 是免安裝的綠色軟體,而且只有 nssm.exe 單一執行就可以運行。只要從 官網下載 壓縮檔回來,將 nssm.exe 解壓縮到 C:\Windows 底下就直接可以用了!

    注意: 使用 nssm 註冊服務時,它會自動在你的 事件記錄器 中註冊一個 名為 NSSM 的 事件來源 (Event Source)。

  2. 使用 GUI 介面安裝 Windows 服務

    請以系統管理員身份執行 Command Prompt (cmd.exe),並使用以下命令執行安裝:

    nssm install MyService
    

    這個命令事實上會自動開啟 nssm 的 GUI 圖形化介面,非常容易上手好操作:

    nssm 的 GUI 圖形化介面

    設定好之後,按下 Install service 就會自動安裝成功!?

    如果要移除 Windows 服務,也可以這樣執行,也一樣會跳出 GUI 介面:

    nssm remove MyService
    
  3. 使用 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
    
  4. 使用 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 服務執行參數為何。

  • Application

    解释

    REM 應用程式路徑 REM 預設: 應用程式完整路徑 (C:\EC.Services\訂單處理服務.exe) nssm get MyService Application REM 工作目錄 REM 預設: 應用程式所在目錄路徑 (C:\EC.Services) nssm get MyService AppDirectory REM 應用程式參數 REM 預設: 無內容 nssm get MyService AppParameters
  • Details

    解释

    REM 服務的顯示名稱 (顯示名稱可以跟服務名稱不同) REM 預設: 服務名稱 (MyService) nssm get MyService DisplayName REM 服務詳細描述 REM 預設: 無內容 nssm get MyService Description REM 服務啟動方式 REM 預設: SERVICE_AUTO_START (自動啟動) nssm get MyService Start
  • Log on

    解释

    REM 服務啟動方式 REM 預設: LocalSystem (本機系統) nssm get MyService ObjectName REM 服務啟動方式 REM 預設: SERVICE_WIN32_OWN_PROCESS nssm get MyService Type
  • Dependencies

    REM 相依服務
    REM 預設: 無內容
    nssm get MyService DependOnService
    
  • Process

    解释

    REM 執行優先權 REM 預設: 無內容 nssm get MyService AppPriority REM 是否不要啟動一個隱藏的 Console 視窗來執行服務 (有些程式沒有 STDIN 輸入會掛掉) REM 預設: 0 (要啟動一個隱藏的 Console 視窗來接受 STDIN 輸入) nssm get MyService AppNoConsole REM 要用多少 CPU 核心執行 (CPU Affinity) REM 預設: All (所有 CPU 核心) nssm get MyService AppAffinity
  • Shutdown

    解释

    REM 判斷要用什麼方式傳遞訊號給應用程式 REM 預設: 0 (代表什麼訊號都傳給應用程式) nssm get MyService AppStopMethodSkip REM 當送出 Control-C 的時候要等待幾豪秒進行優雅結束 (Gracefully Shutdown) REM 預設: 1500 豪秒 nssm get MyService AppStopMethodConsole REM 當送出 WM_CLOSE 訊號的時候要等待幾豪秒進行優雅結束 (Gracefully Shutdown) REM 預設: 1500 豪秒 nssm get MyService AppStopMethodWindow REM 當送出 WM_QUIT 訊號的時候要等待幾豪秒進行優雅結束 (Gracefully Shutdown) REM 預設: 1500 豪秒 nssm get MyService AppStopMethodThreads
  • Exit actions

    解释

    REM 如果程式在幾豪秒之內就死掉就延遲啟動 REM 預設: 1500 豪秒 nssm get MyService AppThrottle REM 應用程式結束時的預設行為 REM 預設: Restart (重啟服務) nssm get MyService AppExit Default REM 服務重啟的延遲啟動豪秒數 REM 預設: 0 豪秒 nssm get MyService AppRestartDelay
  • I/O

    解释

    REM 應用程式的 STDOUT 訊息要輸出到哪個檔案 REM 預設: 無內容 nssm get MyService AppStdout REM 應用程式的 STDERR 訊息要輸出到哪個檔案 REM 預設: 無內容 nssm get MyService AppStderr
  • File rotation

    解释

    REM 設定是否要對記錄檔進行自動 Rotate 處理 REM 預設: 1 nssm get MyService AppRotateFiles REM STDOUT 訊息紀錄檔的建立方式 REM 預設: 4 (開啟現有的紀錄檔進行寫入) nssm get MyService AppStdoutCreationDisposition REM STDERR 訊息紀錄檔的建立方式 REM 預設: 4 (開啟現有的紀錄檔進行寫入) nssm get MyService AppStderrCreationDisposition REM 服務在執行的時候也可以 Rotate 記錄檔 REM 預設: 0 (預設要停用服務才會 Rotate 記錄檔) nssm get MyService AppRotateOnline REM 當記錄檔已經超過幾豪秒就自動 Rotate REM 預設: 86400 nssm get MyService AppRotateSeconds REM 當記錄檔已經超過多少 Bytes 就自動 Rotate REM 預設: 1048576 nssm get MyService AppRotateBytes
  • Environment

    REM 服務啟動前先設定好環境變數
    REM 預設: 無內容
    nssm get MyService AppEnvironmentExtra
    

注意「雙引號」傳遞應用程式參數可能造成的問題

在 Command Prompt 命令提示字元中,一直以來最被詬病的問題,就是「雙引號」的跳脫處理會讓整個命令變的可讀性極差,所以當你需要傳遞參數到服務應用程式時,需要傳入執行的參數包含「雙引號」,那就有地方要特別注意了!

假設你的應用程式參數必須包含空白字元,所以需要使用雙引號框起來:

  1. 手動執行的寫法

    "C:\EC.Services\訂單處理服務.exe" "This is one argument"
    
  2. 使用 nssm 的安裝命令

    nssm install "訂單處理服務" "C:\EC.Services\訂單處理服務.exe" """This is one argument"""
    

假設你要執行 Java 應用程式,參數可能很複雜,例如:

  1. 手動執行的寫法

    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% 可以取得當前目錄的路徑!

  2. 使用 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=1B=2C=3 等等,那麼你應該在建立好服務且尚未啟動服務之前,先這樣設定好環境變數:

nssm set MyService AppEnvironmentExtra "A=1" "B=2" "C=3"

公司简介

 

自1996年以来,公司一直专注于域名注册、虚拟主机、服务器托管、网站建设、电子商务等互联网服务,不断践行"提供企业级解决方案,奉献个性化服务支持"的理念。作为戴尔"授权解决方案提供商",同时提供与公司服务相关联的硬件产品解决方案。
备案号: 豫ICP备05004936号-1

联系方式

地址:河南省郑州市经五路2号

电话:0371-63520088

QQ:76257322

网站:800188.com

电邮:该邮件地址已受到反垃圾邮件插件保护。要显示它需要在浏览器中启用 JavaScript。