☰
NSSM 2.10 实战:把 exe 封装成 Windows 服务,实现开机自启与崩溃重启
2026/10/8 2:06:09 网站建设 项目流程

简介:这份压缩包提供 NSSM 2.10 在 Windows 平台上的完整发行资源,面向需要把任意可执行程序或脚本注册为 Windows 服务的开发与运维人员,用于解决普通程序无法随系统自动启动、无人值守运行的问题。NSSM(Non-Sucking Service Manager)以轻量、可直观配置服务参数而著称,支持设置服务名、启动参数、依赖关系与日志输出,能替代系统自带服务管理工具处理非标准启动问题,并已适配 Windows 10 环境。包内共 24 个文件,其中 win32 与 win64 目录各含一个可直接运行的 nssm.exe,另外还有 7 个头文件和 6 个 C++ 源文件,对应服务注册、事件记录、注册表操作等实现,配套 .sln/.vcproj/.dsp 工程文件、README 与 ChangeLog 便于编译和查阅版本差异,整体大小仅 158KB。目前已有 223 人浏览学习。解压后既能直接调用命令行或界面工具将应用封装为后台服务,也能通过源码深入理解 Windows 服务管理机制,适合服务自启、无人值守运行和故障诊断等场景。

1. 在 win10 上把 exe 变成服务,为什么绕不开 nssm-2.10

NSSM 全称 Non-Sucking Service Manager,nssm-2.10 这个版本是很多运维手里一直留着的 Windows 服务封装工具 ZIP 包。它解决一个特别具体的痛点:在 win10 上想把任意一个 exe、批处理或脚本变成开机自启、崩溃自动重启、日志有地方落的 Windows 服务,靠任务计划程序和 sc.exe 都差点意思。NSSM 2.10 虽然版本老,但在 win10 专业版和 22H2 上依然能正常注册服务,配置入口直观,服务一旦注册进服务管理器,就和系统服务一样受 SCM(服务控制管理器)统一管理,开机自启、依赖关系、恢复策略都能在图形界面里调。适合谁?被 nginx、MySQL、Java 应用在 Windows 上开机自启问题折磨过的运维和开发,以及所有想把手写脚本变成“真正的服务”的人。

2. 选型:NSSM 和 winsw、sc.exe 的边界在哪里

在动手之前,先把 Windows 下把程序变服务的四条路说清楚:系统自带的 sc.exe、Windows Resource Kit 里的 srvany、winsw 和 NSSM。选错方案的代价不在安装那一刻,而在后面投入使用时反复调不通。这一章把每个方案的边界捋一遍,你就能理解为什么大家最后普遍落到 NSSM 上。

2.1 sc.exe 只负责注册,不负责把服务养活

sc.exe 是 Windows 自带的,能创建服务,但它的能力边界很清楚:把服务注册进去、设置启动类型、查询状态,仅此而已。它不会帮你管理日志,不会在进程崩溃后自动恢复,也不太适合作为长期守护方案。常见做法是只拿它做最基础的注册和删除,真正的守护逻辑交给 NSSM 这类封装工具。

用 sc.exe 创建服务的命令长这样:

sc create MyService binPath= "C:\tools\app.exe --port 8080" start= auto

这条命令把 app.exe 注册成名为 MyService 的服务,开机自启。注意 sc.exe 对格式非常挑剔,binPath=的等号后面必须有空格,start= auto也一样,少一个空格命令就会报参数错误。把这个例子放在这里不是让你用它,而是让你对比后面的 NSSM 用法:sc.exe 创建的服务的 ImagePath 直接指向你的程序,程序一旦崩了,服务就停止,没有任何恢复策略;日志要么程序自己写文件,要么你看不到任何输出。这对 nginx、MySQL 这类需要长时间跑的进程来说不够用。

比 sc.exe 更老一点的还有 Windows Resource Kit 里的 srvany,它能把任意程序注册为服务,但同样没有日志重定向、没有进程守护、没有图形配置界面,配置全靠改注册表,现在已经很少有人在新项目里用了。如果你的同事提起 srvany,把它当作一个历史方案就行,不值得为此引入新的依赖。所以在 win10 环境下,sc.exe 更适合做一次性注册工具,不适合做长期守护方案。如果只是临时注册一个服务,用 sc.exe 没问题;如果这个程序是生产依赖,后面迟早要换成 NSSM 或 winsw。

2.2 winsw 和 NSSM 都托管程序,差在配置方式和运维习惯

winsw 是另一个流行方案,很多人在“nginx 服务使用 winsw 还是 nssm”这个问题上纠结。winsw 的核心是 XML 配置,把一个 exe 包在配置文件里,然后安装成服务。它的优点是配置文件可以进版本库,适合批量部署和自动化运维;缺点是调试时改配置要改 XML、重装服务,win10 上新手容易在 XML 格式上翻车。

一个典型的 winsw 配置大概是这样的:

<service> <id>MyService</id> <name>MyService</name> <description>My demo service</description> <executable>C:\tools\app.exe</executable> <arguments>--port 8080</arguments> <log mode="roll-by-size"> <sizeThreshold>10240</sizeThreshold> </log> </service>

然后执行winsw install、winsw start。这套流程在纯命令行环境里非常干净,但如果你的使用场景是“在 win10 服务器上手工装服务、时不时看日志、调参数”,NSSM 的 nssm edit 图形界面会更顺手,日志重定向、退出码策略、环境变量都能在窗口里直接改。我的判断是:批量部署、有配置管理工具的团队用 winsw;单机手工运维、需要经常调试的选 NSSM。两者都能把 nginx 这类程序托管成服务,差别不在能力,而在使用习惯。

2.3 NSSM 2.10 的适用边界和反例

NSSM 也不是万能的。它托管的是“一个可执行文件 + 参数 + 工作目录 + 环境变量”,服务启动时由 NSSM 创建一个被托管进程,并监控这个进程的退出码。以下三类场景不适合直接用 NSSM。

第一类,带图形界面的交互程序。NSSM 托管的服务运行在 Session 0(服务会话),普通 GUI 程序在服务会话里显示不出来,窗口不会出现在你的桌面上,程序可能启动后一直停在初始化界面。

第二类,自身会 fork 子进程并且主进程会提前退出的程序。NSSM 判断服务是否存活看的是你配置的那个启动进程,主进程一旦正常退出,NSSM 会认为服务结束,不会继续等子进程。像某些 Java 启动器,主进程拉起来 JVM 后就退出,直接用 NSSM 托管的服务会反复重启。

第三类,需要多实例且每个实例配置差异很大的程序。NSSM 支持注册多个服务名,但每个服务名的配置要单独维护,服务多了以后注册表里的配置项会变得难管理,这种情况更建议用容器或虚拟机托管。

理解了这个边界,后面的配置逻辑就顺了:你只需要关心“NSSM 启动哪个进程、这个进程怎么退出、退出后怎么办”。至于进程内部怎么 work,NSSM 不关心,也不需要关心。

3. 用 NSSM 2.10 在 win10 装服务的完整命令链

这一章开始动手。假设场景是:手头有一个 app.exe(比如一个自己写的 Web 服务),要在 win10 上跑成开机自启的服务。按下面的顺序走,每一步都有对应的命令和检查方式。

3.1 解压和路径准备:32 位和 64 位别拿错

nssm-2.10 的 ZIP 解压后,里面一般有 win32 和 win64 两个目录,分别对应 32 位和 64 位版本的 nssm.exe。win10 基本都是 64 位系统,应该拿 win64 目录下的 nssm.exe。拿错的话也不是完全不能用,NSSM 32 位版在 64 位系统上也能注册服务,但服务管理器里部分显示可能异常,而且 32 位进程去启动 64 位程序时会遇到文件重定向问题,属于能省就别省的操作。

常见做法是把 nssm.exe 单独放到一个固定目录,比如 C:\tools\nssm\nssm.exe,而不是每次从解压临时目录运行。因为 NSSM 安装服务时会把自身路径写入注册表,服务安装后再移动 nssm.exe,服务启动时找不到主程序会直接失败。这也是新手容易踩的坑。

准备好之后,用管理员权限打开 CMD 或 PowerShell。注意必须是管理员权限,普通终端在创建服务时大概率会报“拒绝访问”。

3.2 交互式安装:先 nssm install 打开图形界面

最简单的安装方式是直接运行:

nssm install MyService

这条命令会弹出 NSSM 的 GUI 配置窗口。在 Path 一栏填 app.exe 的完整路径,比如 C:\app\app.exe;Startup directory 会自动带出来,一般不用改;Arguments 填需要带的参数,比如--port 8080。填完之后点击 Install service,服务就注册成功了。

GUI 的好处是选项卡里能看到 Logs、Environment、Exit actions 这些参数,适合第一次使用的人熟悉 NSSM 有哪些配置项。GUI 窗口在服务器远程桌面里偶尔会出现显示不全的情况,而且每次改配置都要开窗口,批量操作效率太低。所以我更常用的是下面的命令行方式。

打开图形界面的命令同样适用于已有服务,运行nssm edit MyService就会打开配置窗口修改现有服务。

3.3 命令行安装:一台机器上能复制的完整命令

在脚本化或远程维护场景里,用命令行装服务是更可控的方式。完整命令如下:

nssm install MyService "C:\app\app.exe" --port 8080 nssm set MyService AppDirectory "C:\app" nssm set MyService AppStdout "C:\app\logs\stdout.log" nssm set MyService AppStderr "C:\app\logs\stderr.log" nssm set MyService AppRotateFiles 1 nssm start MyService

逐条说明。第一条把服务名定义为 MyService,程序路径和参数写在后面;第二条设置 AppDirectory,这个参数指定程序的工作目录。很多程序启动时要读当前目录下的配置文件,不设这一项,程序可能起不来,这是后面避坑章的主角;第三条和第四条把标准输出和标准错误重定向到文件,方便排查问题;第五条开启日志轮转;第六条启动服务。

安装完成后用nssm status MyService查看状态,输出 SERVICE_RUNNING 就说明正常运行。如果用nssm start MyService启动时提示服务已经启动,多半是安装之后服务的启动类型是“自动”,系统已经拉起来了。

3.4 服务参数查询与批量修改

服务装好之后,参数不是写死的,随时可以改。常用命令是 nssm set、nssm get、nssm edit 三件套。nssm get 用来读当前值,比如:

nssm get MyService AppDirectory nssm get MyService AppExit

nssm set 用来改值。下面命令把日志文件路径改到 D 盘:

nssm set MyService AppStdout "D:\logs\app.log" nssm restart MyService

nssm edit 则是打开图形界面。三者的选择规律是:查看用 get,脚本修改用 set,人工调试用 edit。注意改完配置后,已经在运行的服务不会马上生效,需要 restart 一次。NSSM 自己没有热加载机制,这点和 nginx -s reload 不一样,别指望改配置即时生效。

4. 日志、环境变量和恢复策略:让服务真正跑得久

服务能启动了只是第一步。实际跑生产的时候,日志、环境变量、异常退出策略才是决定这个服务能不能长期跑下去的关键。这一章把 NSSM 里最常用的几组参数讲透。

4.1 日志重定向:不写出来就不知道死在哪

在上一章的安装命令里已经出现了 AppStdout 和 AppStderr。这两个参数做的事情是:把被托管进程的标准输出和标准错误写到文件。很多程序(尤其是 nginx、脚本类程序)本身不写日志文件,只往控制台打印,直接注册成服务后输出无处可去,报错信息全丢。

配置日志文件时,建议 stdout 和 stderr 分开两个文件,避免出错信息被正常日志刷掉。文件目录一定要提前建好,NSSM 不会自动创建目录,如果路径不存在,输出会静默失败,日志文件不会出现,你还会以为程序没输出。

日志轮转在 3.3 已经开过,这里重点说两个参数。AppRotateFiles=1 开启轮转,AppRotateBytes 指定轮转阈值。例如:

nssm set MyService AppRotateFiles 1 nssm set MyService AppRotateBytes 10485760

10485760 是 10MB 的字节数。达到这个大小后,NSSM 会把当前日志重命名为带时间戳的文件,再新建一个空日志继续写,相当于自己做了一个按文件大小切割的轮转,避免日志无限膨胀写满磁盘。

4.2 环境变量和工作目录:两个最容易忽视的配置

win10 下跑服务,经常出现“服务显示运行中,但程序内部报找不到文件、找不到命令”的现象。原因有两个,都出在 NSSM 的默认行为上。

第一个是工作目录。服务由 SCM 启动,默认工作目录不是程序所在目录,而是 system32 之类的系统目录。程序如果是相对路径读取配置文件,就会读到不存在的位置。解决办法就是把 AppDirectory 设置成程序目录,上一章已经做了。

第二个是环境变量。NSSM 默认继承的是系统环境变量,不会加载用户环境变量,也不会自动把程序目录加进 PATH。如果你的服务需要调用别的命令,比如脚本里调 python、git,需要额外配置。NSSM 在 GUI 的 Environment 选项卡里可以逐条加,命令行则用 AppEnvironmentExtra:

nssm set MyService AppEnvironmentExtra "PATH=C:\Python311;C:\Program Files\Git\bin"

注意这个参数设置的是 PATH 的追加片段,和系统 PATH 是叠加关系,不是覆盖。如果你在 win10 上安装 MySQL 5.7 之后想让 MySQL 服务读对配置文件,同样要确认工作目录是 MySQL 的 bin 目录,否则它会去默认位置找 my.ini。

4.3 进程守护:退出码策略和自动重启

NSSM 最被看重的功能是“进程死了自动拉起”,对应配置在 Exit actions 里。核心是两个参数:AppExit 和 AppRestartDelay。

AppExit 决定不同退出码对应的动作。最简单的设置是任何退出码都重启:

nssm set MyService AppExit Default Restart

这条命令的意思是:如果进程退出且退出码不是专门定义的某个值,默认执行 Restart。也可以只针对特定退出码做处理,比如退出码 0 是正常结束,不需要重启,退出码 1 是崩溃,要重启:

nssm set MyService AppExit 0 Exit nssm set MyService AppExit 1 Restart

AppRestartDelay 是重启延迟,单位毫秒。这个参数非常关键,不设置的话,进程退出后 NSSM 会马上重启。如果程序启动时需要初始化数据库等资源,瞬间的高频重启会打满 CPU,形成重启风暴。常规做法是设 5 到 10 秒:

nssm set MyService AppRestartDelay 5000

设置了 5 秒延迟后,进程即使持续崩溃,系统也有喘息空间,方便你去看日志定位问题。

4.4 服务依赖:让先启动的服务先起来

当多个服务之间有先后关系时,比如 nginx 依赖本机 MySQL,需要配置服务依赖。NSSM 对应的参数是 AppDependOnService,多个依赖之间用斜杠分隔:

nssm set MyService AppDependOnService MySQL57

这里的 MySQL57 是 MySQL 服务在系统里的服务名,不是显示名。可以用sc query | findstr MySQL查准确的服务名。配置依赖后,SCM 在启动 MyService 之前会先启动 MySQL57,如果 MySQL57 启动失败,MyService 也不会启动,避免出现下游服务先跑起来、连接数据库失败再退出的尴尬。

5. 避坑:NSSM 服务起不来的 5 个常见死法

下面这些问题是实操里反复遇到的,按现象、原因、解决的顺序写,每条都是在 win10 上直接用 NSSM 跑服务时真实会踩到的坑。

5.1 服务状态是 Running,但进程列表里根本没有程序

现象:服务管理器里 MyService 显示“正在运行”,但任务管理器里找不到 app.exe。

原因:NSSM 实际是启动了进程,但进程启动后立刻退出,SCM 看到 NSSM 还没报告退出,就暂时显示运行中。最常见的原因是 AppDirectory 没设置,程序启动时工作目录不对,读不到配置然后自己退出。另一个常见原因是程序路径填成快捷方式或安装引导程序,安装引导程序启动后立即退出,真正的业务进程还没起来。

解决:先nssm edit MyService检查 Path 和 Startup directory,确认 Path 指向真正的 exe,AppDirectory 指向 exe 所在目录。如果仍然秒退,把 AppStdout 和 AppStderr 配好,看程序自己输出了什么错误。

5.2 服务在“启动中”和“已停止”之间反复横跳

现象:服务管理器里状态一直变来变去,CPU 占用飙升,事件查看器里全是同一个服务的启动失败记录。

原因:典型的重启风暴。配置了 AppExit Default Restart,但没设置 AppRestartDelay,进程一崩立即拉起,拉起来又崩,形成循环。

解决:先把恢复策略改成不重启,确认程序本身能手动跑起来:

nssm set MyService AppExit Default Exit nssm stop MyService nssm start MyService

确认稳定运行后,再设置 AppExit Default Restart 和 AppRestartDelay 5000。这样即使再崩,也有 5 秒间隔,不会把 CPU 打满。

5.3 日志文件涨到几个 GB,系统盘被写满

现象:C 盘剩余空间快速下降,打开日志文件发现里面有几 GB 内容。

原因:没开启日志轮转。NSSM 默认情况下会把 stdout 和 stderr 无限追加到同一个文件,服务跑几个月后文件大小很恐怖,磁盘被写满后整个系统变卡,服务也会因为磁盘写不进去而异常退出。

解决:给日志配好轮转:

nssm set MyService AppRotateFiles 1 nssm set MyService AppRotateBytes 10485760

顺带检查一下日志是不是 stdout 和 stderr 混在同一个文件里,混在一起排查问题会非常痛苦,建议分开。

5.4 重启服务时旧进程没被杀死,端口被占用

现象:执行 nssm restart 后,新进程起不来,提示端口被占用,查进程发现旧的 app.exe 还在。

原因:NSSM 停止服务时默认给进程发一个 Ctrl+C 或 WM_CLOSE 信号,进程如果没做优雅退出,NSSM 会等一段时间再强制结束。但如果程序对信号无响应,NSSM 判断超时后可能没有真正杀掉整个进程树,子进程还活着。

解决:配置停止方法更直接一点:

nssm set MyService AppStopMethodConsole 5000 nssm set MyService AppStopMethodWindow 5000 nssm set MyService AppStopMethodThreads 5000 nssm set MyService AppKillProcessTree 1

前几行把三阶段优雅退出等待时间收紧到 5 秒,最后一行是强制杀掉整个进程树。如果确认程序不需要做清理工作,可以把超时调成 1000,让服务停止和重启更快。

5.5 win10 上装服务报“拒绝访问”或者服务无法启动

现象:nssm install 报拒绝访问,或者服务装好后启动报“服务未能在及时时间内响应”。

原因:终端不是管理员权限,或者程序路径放在带用户名的目录下,比如 C:\Users\张三\app.exe。NSSM 的服务默认以 LocalSystem 账户运行,LocalSystem 能读大多数系统目录,但对个别用户目录有访问限制。win10 的 UAC 也会拦普通权限的命令行操作。

解决:全程用管理员身份打开 CMD 或 PowerShell;服务程序放到 C:\app、C:\tools 这类公共目录,路径里不要带用户名,也不要用中文路径。如果程序必须读某个用户目录的数据,可以在服务的 Log on 选项卡里改成指定账户并填好密码,但普通场景不建议这么干,账户密码过期会造成服务起不来。

6. 进阶:装完服务后的验证清单和配置迁移技巧

6.1 验证清单:别让“看起来在跑”骗了你

服务装完不能算完,建议按下面的清单验证一遍再投入使用:

  • nssm status 显示 SERVICE_RUNNING。
  • 服务管理器里确认启动类型是“自动”。
  • 手动重启一次 win10,看服务是否自动拉起。
  • 用 nssm stop 停掉服务,验证崩溃自动恢复策略是否生效。
  • 查看日志目录有 stdout.log 和 stderr.log 输出。

这套验证在 win10 22H2 和 win10 专业版上都适用。如果你配了服务依赖,还要额外验证一下先启动的服务没起来时,下游服务是不是也被挡住了。

6.2 用注册表导出迁移 NSSM 配置

配置迁移是一个实用技巧。NSSM 的服务配置并不存在 NSSM 自己的配置文件里,而是写在注册表 HKLM\SYSTEM\CurrentControlSet\Services<服务名> 下。所以迁移服务到新机器时,除了把程序和 nssm.exe 复制过去,还可以用 reg export 把配置导出来:

reg export "HKLM\SYSTEM\CurrentControlSet\Services\MyService" C:\backup\myservice.reg

新机器上重新安装 NSSM 服务后,导入注册表并重启服务即可。但注意 ImagePath 里写的是 nssm.exe 的绝对路径,两台机器如果 nssm 所在目录不同,导入后要手工改一下,否则服务找不到 nssm 本体。

我自己的习惯是每次装完一个新服务,把安装命令、关键参数、日志路径这三样用记事本存一份放在 nssm.exe 旁边。Windows 服务这东西,装的时候十分钟,排查的时候可能耗一下午,留一份命令清单就是给自己留后悔药。遇到服务异常先看 stderr 日志再下结论,别急着重启,多数问题在日志里都有明确答案。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询