Windows 服务注册神器:WinSW 与 nssm 详解
Windows 服务注册神器WinSW 与 nssm 详解一、为什么需要注册为服务在 Windows Server 上直接双击运行一个.bat、.exe或java -jar存在以下问题登录才能运行服务器重启后只有用户登录桌面程序才会启动。容易被误关有人不小心关掉命令行窗口程序就挂了。崩溃后无法自动拉起程序异常退出后无人值守就不会重启。缺乏统一管理无法用net start/stop或服务控制台统一操作。把程序注册为 Windows 服务后系统启动时自动运行无需登录程序崩溃后可以自动重启通过services.msc或命令启停运维标准化二、工具选型WinSW vs nssm特性WinSWnssm开源✅ (MIT)✅ (Public Domain / Unlicense)配置方式XML 文件命令行参数或编辑 GUI功能丰富度支持日志轮转、多个停止方式、依赖、环境变量支持日志、自动重启、进程优先级、限制 CPU 等易用性需手写 XML但模板化后复用方便一行命令安装简单直接社区活跃度活跃广泛用于 Jenkins、Nexus 等经典老牌稳定推荐场景需要复杂配置、日志轮转、多种停止方法快速将任意程序转为服务追求极简新手建议先用 nssm 快速上手后续需要精细控制时再迁移到 WinSW。两者可以混用。三、nssm 详细教程3.1 下载与准备访问 nssm 官网https://nssm.cc/download下载最新稳定版nssm-2.24.zip或更新。解压后得到win32和win64文件夹根据系统选择对应的nssm.exe。将nssm.exe复制到一个固定路径如C:\Windows已加入 PATH或放在你的应用目录。为方便全局使用建议丢到C:\Windows这样任何位置都能执行nssm命令。3.2 安装服务以部署C:\myapp\app.jar为例Java 应用端口 8080。命令格式nssm install 服务名 程序路径 [参数列表]实际操作nssm install MyJavaApp java -jar C:\myapp\app.jar --server.port8080此时会弹出一个配置窗口GUI你可以进一步设置Application选项卡程序路径和启动参数已经填好可微调。Details选项卡显示名称Display name、描述Description、启动类型Startup type设为Automatic。Log on选项卡一般保持“Local System account”或指定专用账户。Process选项卡“Shutdown”标签设置停止程序的方式。Terminate是直接杀死进程也可改为Control-C或发送关闭 URL。Exit actions选项卡重要默认“Restart”表示程序退出后自动重启。可设置重启延迟如 10 秒。I/O选项卡可设置日志输出文件路径stdout/stderr。Environment选项卡可添加环境变量如JAVA_HOMEC:\Program Files\Java\jdk-11。配置完成点击Install service按钮即可安装。3.3 纯命令行安装无 GUI如果你在 Server Core 或想脚本化nssm install带上所有参数nssm install MyJavaApp C:\Program Files\Java\jdk-11\bin\java.exe -jar C:\myapp\app.jar --server.port8080 nssm set MyJavaApp AppDirectory C:\myapp nssm set MyJavaApp DisplayName My Java Application nssm set MyJavaApp Description 公司核心业务 Java 服务 nssm set MyJavaApp Start SERVICE_AUTO_START nssm set MyJavaApp AppStdout C:\myapp\logs\stdout.log nssm set MyJavaApp AppStderr C:\myapp\logs\stderr.log nssm set MyJavaApp AppEnvironmentExtra JAVA_HOMEC:\Program Files\Java\jdk-11 nssm set MyJavaApp ObjectName LocalSystemAppDirectory程序工作目录重要。如果不设程序可能找不到配置文件。Start SERVICE_AUTO_START自动启动延迟自动启动可用SERVICE_DELAYED_AUTO_START。3.4 启动/停止/管理服务# 启动服务 nssm start MyJavaApp # 停止服务 nssm stop MyJavaApp # 重启服务 nssm restart MyJavaApp # 查看服务状态 nssm status MyJavaApp # 查看所有已注册的 nssm 服务无专门命令用 services.msc 或 sc query你也可以用系统自带的net start/stop或sc命令操作因为 nssm 注册的就是标准 Windows 服务。3.5 修改配置nssm edit MyJavaApp会重新打开 GUI 配置窗口可修改参数。修改后需要重启服务才能生效。3.6 卸载服务nssm remove MyJavaApp confirmconfirm跳过确认提示。服务必须已停止才能卸载。如果服务还在运行先nssm stop MyJavaApp。3.7 nssm 高级捕获控制台程序并实现优雅停止nssm 默认的TerminateProcess可能让 Java 或 Node.js 无法优雅关闭。可以在 Process 选项卡中将“Shutdown”方法改为Control-C发送 CtrlC 信号并适当设置超时时间。对于 HTTP 服务还可以用 URL 方式调用关闭接口如 Spring Boot 的/actuator/shutdown这需要在 Shutdown 标签选择 HTTP填写 URL 和 Method。四、WinSW 详细教程WinSWWindows Service Wrapper由一个.exe文件和一个.xml配置文件配对组成。4.1 下载与准备访问 WinSW GitHub Releaseshttps://github.com/winsw/winsw/releases下载最新的WinSW-x64.exe64位或WinSW-x86.exe。将下载的 exe 重命名为一个有意义的名字如myapp-service.exe并放到你的应用程序目录例如C:\myapp\。在同一目录下创建一个同名的.xml文件即myapp-service.xml。WinSW 会自动寻找同名的 xml 作为配置。4.2 编写配置文件myapp-service.xml完整注释模板service!-- 服务唯一标识 ID不可重复 --idMyJavaApp/id!-- 服务显示名称services.msc 中看到的名字 --nameMy Java Application/name!-- 服务描述可选 --description公司主业务Java服务端口8080/description!-- 要运行的可执行文件可以是 exe、bat、java 等 --executablejava/executable!-- 启动参数 --arguments-jar C:\myapp\app.jar --server.port8080/arguments!-- 工作目录通常与可执行文件所在目录一致 --workingdirectoryC:\myapp/workingdirectory!-- 停止方式 - stopexecutable/stoparguments: 执行停止命令 - 如果注释掉默认发送 CtrlC等待超时后强杀 --!-- 对于 Java 程序通常直接让 WinSW 发送 CtrlC 即可无需额外配置 --!-- 或者使用特定的停止可执行文件例如 Spring Boot 的 shutdown 脚本 --stopexecutablecurl/stopexecutablestoparguments-X POST http://localhost:8080/actuator/shutdown/stoparguments!-- 日志路径及配置 --logpathC:\myapp\logs/logpathlogmoderoll-by-size!-- 单个日志文件最大 10MB --sizeThreshold10240/sizeThreshold/log!-- 服务启动类型Automatic 开机自启 --startmodeAutomatic/startmode!-- 失败后操作5 秒后重新启动 --onfailureactionrestartdelay5 sec/!-- 重置失败计数的时间防止快速循环重启 --resetfailure1 hour/resetfailure!-- 环境变量 --envnameJAVA_HOMEvalueC:\Program Files\Java\jdk-11/envnamePATHvalue%JAVA_HOME%\bin;%PATH%//service4.3 常用配置项说明XML 标签必须说明id是服务的内部名称不可与其他服务重复name是服务的显示名称executable是要运行的程序路径可以是绝对路径或 PATH 中能找到的命令arguments否传给可执行文件的参数workingdirectory否工作目录建议设置否则可能找不到配置文件logpath否日志存放目录不设置则默认在同目录下log mode否日志模式roll-by-size(按大小轮转)、roll-by-time(按时间)、reset(每次重启清空)stopexecutable否用于停止服务的命令未设置则默认发送 CtrlC 信号stoptimeout否等待服务停止的超时时间默认 15 秒startmode否启动类型Automatic(自动)、Manual(手动)、Disabled(禁用)onfailure否失败后的动作restart、reboot、none。可设置delay延迟env否设置环境变量可多次出现4.4 安装、管理、卸载打开管理员命令提示符进入应用程序目录C:\myapp\执行# 安装服务 myapp-service.exe install # 启动服务 myapp-service.exe start # 停止服务 myapp-service.exe stop # 重启服务 myapp-service.exe restart # 查询服务状态 myapp-service.exe status # 刷新服务重新读取 xml 配置文件但必须重启服务才生效 myapp-service.exe refresh # 卸载服务 myapp-service.exe uninstall安装完成后去services.msc就能看到你的服务可手动启停或设置启动类型。4.5 多服务管理技巧WinSW 支持同时管理多个服务。只需为每个服务准备独立的exe和xml文件可复制同一个 exe 并重命名放在各自的目录下即可。例如C:\services\app1\app1-service.exe C:\services\app1\app1-service.xml C:\services\app2\app2-service.exe C:\services\app2\app2-service.xml注意id必须全局唯一。五、实战示例示例 1用 nssm 注册 Node.js Express 应用假设项目在C:\www\myapi入口server.js端口 3000。nssm install MyAPI node C:\www\myapi\server.js nssm set MyAPI AppDirectory C:\www\myapi nssm set MyAPI DisplayName My API Server nssm set MyAPI Start SERVICE_AUTO_START nssm set MyAPI AppStdout C:\www\myapi\logs\out.log nssm set MyAPI AppStderr C:\www\myapi\logs\err.log nssm start MyAPI示例 2用 WinSW 注册 Python Flask 应用使用 waitressC:\apps\flaskapp\run.py为入口。先创建虚拟环境并安装依赖。flaskapp-service.xmlserviceidFlaskApp/idnameFlask Web App/namedescriptionFlask application with waitress/descriptionexecutableC:\apps\flaskapp\venv\Scripts\python.exe/executableargumentsC:\apps\flaskapp\run.py/argumentsworkingdirectoryC:\apps\flaskapp/workingdirectorylogpathC:\apps\flaskapp\logs/logpathonfailureactionrestartdelay10 sec//service安装flaskapp-service.exe install然后启动。示例 3注册 Nginx 为服务用 WinSW之前我们提到过Nginx 官方无服务支持。用 WinSW 配置serviceidnginx/idnameNginx Web Server/nameexecutableC:\nginx\nginx.exe/executablestartarguments-g daemon off;/startarguments!-- 告诉 nginx 在前台运行否则会后台退出 --stopexecutableC:\nginx\nginx.exe/stopexecutablestopargument-s/stopargumentstopargumentstop/stopargumentworkingdirectoryC:\nginx/workingdirectorylogpathC:\nginx\logs/logpath/service这里-g daemon off;是关键因为 nginx 默认会以守护进程方式运行会导致 WinSW 误认为服务已结束。六、常见问题与排查1. 服务安装后无法启动日志报“系统找不到指定的文件”检查executable路径是否正确是否是绝对路径或者是否在 PATH 中。检查workingdirectory是否存在。如果是 Java/Python 程序确保系统环境变量里有对应的可执行文件。2. 服务启动后马上停止用cmd手动运行同样的命令看是否正常。如果不正常是程序本身问题。检查工作目录是否导致配置文件无法读取。对于某些程序如 Nginx必须配置前台运行参数。查看日志nssm 可使用nssm edit查看 I/O 设置WinSW 有logpath。3. 停止服务时无法优雅关闭nssm将 Shutdown 方法改为Control-C或使用 HTTP URL 方式。WinSW配置stopexecutable发送关闭指令。4. 服务依赖网络但启动时网络未就绪nssm 不支持直接添加依赖但可以通过sc config 服务名 depend DHCP/Netman添加依赖。WinSW 可以通过depend标签添加依赖关系dependEventlog/dependdependW32Time/depend5. 权限问题服务默认以LocalSystem账户运行权限很高。如需访问网络共享可能需要指定域账户在services.msc的“登录”选项卡中修改。服务无法访问交互桌面不要尝试弹出 GUI 窗口。6. 卸载服务时提示“服务已标记为删除”先关闭所有services.msc和事件查看器窗口然后重试。七、总结步骤nssmWinSW安装nssm install 服务名 命令准备exe和xml运行exe install配置命令行nssm set或 GUInssm edit编辑 XML 文件日志可在 GUI 中设置 I/O 重定向XML 中配置logpath和log卸载nssm remove 服务名 confirmexe uninstall建议学习路径先用 nssm 把一个 Java jar 或 Node 程序注册为服务体验流程再尝试用 WinSW 配置日志轮转和失败重启感受更丰富的控制力。掌握了服务注册你就彻底解决了“程序如何在 Windows 上稳定运行”的核心问题。配合前面学到的 Nginx、Tomcat、IIS 部署你已经能独立管理 Windows 服务器上的绝大多数业务了。