☰
nssm-2.24.zip 使用指南:将 exe 注册为 Windows 服务
2026/10/6 14:13:18 网站建设 项目流程

简介:nssm-2.24.zip 面向需要将 Spring Boot 应用部署为 Windows 后台服务的 Java 开发者与运维人员,尤其适合不熟悉 Windows 服务底层机制、希望免去复杂配置的初中级使用者。NSSM 以简捷高效著称,只需选定 Java 执行文件、配置 jar 路径与启动参数、设定工作目录,即可把应用平滑注册为系统服务,并内置日志管理与自动恢复机制,异常中断后可自动重启,便于故障排查与长期稳定运行。压缩包共 35 个文件,约 344KB,包含 13 个 h 头文件与 12 个 cpp 源文件构成的核心实现,另有 2 个 exe 可执行程序、2 个 txt 说明文档,以及 rc、mc、cmd、vcproj、sln、ico 等工程与资源文件,覆盖 win32 与 win64 两套可执行版本,源码与工程结构完整。目前已有 266 人学习下载,适合希望快速落地 Spring Boot Windows 服务化部署、并了解其内部实现与排错思路的读者参考。

1. nssm-2.24.zip 到底是什么:把一个 exe 变成 Windows 服务的最后一公里

手里有个自己写的采集程序、一个 Python 脚本、一个 Node 小工具,双击能跑,关掉窗口就停,服务器一重启就彻底失联。这种场景下,nssm-2.24.zip 就是那个被反复翻出来的压缩包。nssm 全称 Non-Sucking Service Manager,干的事非常单一:把任意一个可执行程序注册成 Windows 原生服务,让它开机自启、崩溃自拉、日志可控。2.24 是它流传最广的一个版本号,网上搜 nssm 出来的教程九成都在用它。

它解决的不是“怎么写程序”,而是“怎么让程序在 Windows 上像个服务一样活着”。适合谁?适合那些不想为了一个后台进程去啃 Windows Service API、不想装一堆运行时、只想把现成的 exe 或脚本挂上去就跑的运维和开发。读完这篇,你能拿到一套从解压到排错的完整路径,而不是只知道“有个工具叫 nssm”。

2. 解压之后先别急着 install:nssm 的目录结构与版本选择

2.1 32 位和 64 位到底选哪个

nssm-2.24.zip 解压出来通常长这样:根目录下有一个win32文件夹和一个win64文件夹,各自里面放着一份nssm.exe。这不是让你两个都用,而是按目标机器的架构二选一。

判断方法很直接,在目标机器上开 PowerShell:

# 查看操作系统架构,AMD64 就选 win64 echo $env:PROCESSOR_ARCHITECTURE

输出AMD64用win64\nssm.exe,输出x86用win32\nssm.exe。选错的后果不是立刻报错,而是服务能装上、能启动,但在某些调用路径上行为诡异,这种玄学问题排查起来最费时间。

我一般会把选中的那份nssm.exe单独复制到一个固定目录,比如C:\tools\nssm\nssm.exe,然后把该目录加进系统 PATH。这样后面所有命令直接敲nssm就行,不用每次写一长串路径。注意:nssm 本身不需要安装,它就是个绿色 exe,复制走就能用。

2.2 为什么是 2.24 而不是更新的版本

nssm 官方后来有过 2.24 之后的构建,但 2.24 之所以被大量教程和脚本锁定,是因为它的命令行接口稳定、行为可预期,网上能搜到的参数说明几乎都对应这个版本。生产环境里,一个“大家都知道怎么用”的旧版本,往往比一个“参数可能变了”的新版本更省心。

需要说清楚的是:nssm 不是唯一方案。Windows 自带的sc create也能注册服务,但它对“程序崩溃后自动重启”“工作目录设置”“stdout/stderr 重定向”这些需求支持得很别扭,经常要配合一堆包装脚本。nssm 的价值就在于把这些常见诉求做成了几个参数。选它的理由不是它多强,而是它把 80% 的场景用最低成本覆盖了。

2.3 服务账户:LocalSystem 不是万能钥匙

安装服务时会涉及运行账户。默认走 LocalSystem,权限最大,能访问大多数本地资源。但如果你的程序要访问网络共享、要读某个域用户才能读的目录,LocalSystem 反而会失败,因为它是本机账户,出去访问时身份不对。

常见做法是改成具体的域账户或本地管理员账户:

# 安装时指定运行账户,注意域名或机器名前缀 nssm install MyService "C:\path\to\app.exe" nssm set MyService ObjectName "DOMAIN\user" "password"

参数说明:ObjectName设的是服务登录身份,第一个值是账户名,第二个是密码。密码里有特殊字符时用引号包住。改完账户后建议手动nssm restart MyService验证一次,因为账户权限问题往往要等服务真正跑起来访问资源时才暴露。

3. 用 nssm 把程序注册成服务的完整命令链路

3.1 最小可用安装:三条命令跑通

假设你有一个C:\apps\collector\collector.exe,要把它做成开机自启的服务。最简路径如下:

# 第一步:注册服务,指定可执行文件 nssm install CollectorService "C:\apps\collector\collector.exe" # 第二步:设置工作目录,程序里如果用相对路径读配置,这步不能省 nssm set CollectorService AppDirectory "C:\apps\collector" # 第三步:启动服务 nssm start CollectorService

逻辑说明:install只负责把服务登记进系统,不会自动启动。AppDirectory决定进程的工作目录,很多程序读config.json用的是相对路径,不设这个就会去C:\Windows\System32找,然后报“配置文件不存在”。start才是真正拉起进程。

参数说明:服务名CollectorService自己起,别用中文和空格,后面所有命令都靠它引用。可执行文件路径必须用绝对路径,且路径里有空格时整个用引号包住。

3.2 带启动参数的程序怎么配

如果程序需要命令行参数,比如collector.exe --mode=prod --port=8080,不能直接塞进 install 的第二个参数里,要用AppParameters:

# 先正常安装 nssm install CollectorService "C:\apps\collector\collector.exe" # 再单独设置启动参数 nssm set CollectorService AppParameters "--mode=prod --port=8080" # 设置工作目录 nssm set CollectorService AppDirectory "C:\apps\collector"

逻辑说明:nssm 把“可执行文件”和“参数”拆成两个配置项,这样改参数不用重装服务。AppParameters的值会原样拼在 exe 后面,所以参数格式要和你手动在命令行敲的完全一致。

参数说明:如果参数值本身带空格,比如某个路径参数,要在参数内部再加一层引号,写成--config="C:\my config\a.json"。这层引号是给程序看的,不是给 nssm 看的。

3.3 日志重定向:别让程序输出石沉大海

服务方式运行的程序,stdout 和 stderr 默认没有地方去,程序里print或console.log的东西直接消失。排查问题时这是最坑的一点。nssm 支持把输出写到文件:

# 标准输出重定向到文件 nssm set CollectorService AppStdout "C:\apps\collector\logs\stdout.log" # 标准错误重定向到文件 nssm set CollectorService AppStderr "C:\apps\collector\logs\stderr.log" # 开启输出文件自动轮转,避免日志无限增长 nssm set CollectorService AppRotateFiles 1 nssm set CollectorService AppRotateBytes 10485760

逻辑说明:AppStdout和AppStderr分别接管两类输出。AppRotateFiles 1打开轮转,AppRotateBytes设单文件上限,单位是字节,10485760 就是 10MB。超过就切新文件。

参数说明:日志目录必须提前存在,nssm 不会帮你建目录,目录不存在时输出直接丢弃,服务照跑不误,这种“服务正常但没日志”的情况最容易让人误判。建议在安装前先mkdir好。

3.4 崩溃自动重启:AppExit 与 AppThrottle

服务最核心的价值之一是挂了能自己起来。nssm 默认对非零退出码会尝试重启,但重启节奏要控制,否则程序有启动即崩的 bug 时会疯狂重启刷爆日志。

# 设置退出后的动作:restart 表示重启 nssm set CollectorService AppExit Default Restart # 设置重启节流,单位毫秒,这里 5000 表示 5 秒内最多重启一次 nssm set CollectorService AppThrottle 5000 # 设置启动失败后的重试延迟 nssm set CollectorService AppRestartDelay 3000

逻辑说明:AppExit Default Restart是兜底策略,程序任何非正常退出都触发重启。AppThrottle防止重启风暴,AppRestartDelay控制两次重启之间的间隔。

参数说明:AppThrottle设太小(比如 1000)在程序快速崩溃时仍可能产生大量重启记录;设太大(比如 60000)又会让真正需要快速恢复的服务等太久。5000 到 10000 是常见区间,按业务对恢复速度的要求调。

4. 避坑与排查:nssm 服务起不来的五类真实翻车

4.1 服务显示已启动,但进程秒退

现象:nssm start返回成功,服务状态显示 Running,但过几秒再看已经停了,日志里什么都没有。

原因:程序自身启动就失败,比如依赖的 DLL 缺失、配置文件路径不对、端口被占用。因为进程退得太快,nssm 还没来得及捕获输出。

解决:先把AppStdout和AppStderr配好,然后手动在命令行用同样的工作目录和参数跑一遍 exe,看真实报错。命令行能复现的问题,不要指望服务方式能自己好。

4.2 工作目录没设,相对路径全废

现象:命令行手动跑正常,做成服务就读不到配置、找不到模板文件。

原因:服务的默认工作目录是C:\Windows\System32,程序里所有相对路径都基于它解析。

解决:nssm set <服务名> AppDirectory "<程序所在目录>",然后重启服务。这是最高频的一个坑,几乎每个第一次用 nssm 的人都会踩。

4.3 账户权限不足,访问网络资源被拒

现象:服务能启动,但一访问共享目录或数据库就报权限错误,换成手动运行又正常。

原因:服务默认以 LocalSystem 运行,访问外部资源时身份和当前登录用户不同。

解决:nssm set <服务名> ObjectName "<有权限的账户>" "<密码>",然后重启。改完账户后,原来 LocalSystem 能访问的本地路径可能反而不能访问了,要一并检查。

4.4 日志文件不轮转,磁盘被写满

现象:服务跑了几个月,某天突然所有程序异常,一看磁盘满了,罪魁祸首是某个几十 GB 的 stdout.log。

原因:只设了AppStdout,没开轮转。

解决:补上AppRotateFiles 1和AppRotateBytes,然后重启服务。已经写大的日志文件要手动清理。注意轮转只在服务重启或达到阈值时触发,不是实时切割。

4.5 卸载不干净,重装报服务已存在

现象:nssm remove之后重新 install,提示服务名已存在。

原因:remove 时如果没加confirm,或者服务正在运行,可能没删干净。

解决:先nssm stop <服务名>,再nssm remove <服务名> confirm。如果还残留,用sc query <服务名>确认,必要时用sc delete <服务名>兜底。删完再重装。

5. 进阶技巧:用 nssm 管理多实例与验证服务真实状态

5.1 同一程序跑多实例的命名与端口隔离

一个采集程序要同时跑三个不同数据源,最省事的做法是装三个服务,靠服务名和启动参数区分:

# 实例一 nssm install Collector_A "C:\apps\collector\collector.exe" nssm set Collector_A AppParameters "--source=A --port=9001" nssm set Collector_A AppDirectory "C:\apps\collector" # 实例二 nssm install Collector_B "C:\apps\collector\collector.exe" nssm set Collector_B AppParameters "--source=B --port=9002" nssm set Collector_B AppDirectory "C:\apps\collector"

逻辑说明:三个服务共用同一个 exe,靠AppParameters里的--source和--port隔离。这样升级程序时只换一个 exe,三个服务重启即可,不用分别维护三份代码。

参数说明:端口一定要错开,否则第二个实例启动时端口冲突直接失败。服务名建议带业务含义,别用Service1、Service2,半年后自己都认不出来。

5.2 怎么确认服务是真的在干活

服务状态 Running 只代表进程活着,不代表业务正常。我一般用三层验证:

验证层方法判断标准
进程层nssm status <服务名>返回 SERVICE_RUNNING
日志层看 AppStdout 最后几行有近期时间戳的正常输出
业务层访问程序暴露的端口或检查输出文件数据在更新,端口有响应

只看第一层是不够的。我踩过的坑就是服务 Running、日志停在三天前、业务早就卡死了,因为程序内部线程挂了但主进程没退。所以业务层验证不能省,最好配个外部监控定时打一下。

5.3 升级 exe 时的正确姿势

程序要更新,直接覆盖正在运行的 exe 会失败,因为文件被占用。正确顺序是:

# 停服务 nssm stop CollectorService # 确认进程已退出,必要时等几秒 timeout /t 3 # 替换 exe copy /Y "C:\build\collector.exe" "C:\apps\collector\collector.exe" # 启动服务 nssm start CollectorService

逻辑说明:stop之后进程不会瞬间消失,给系统一点时间释放文件句柄。copy /Y覆盖时不提示确认。

参数说明:如果程序有多个实例,每个都要停、换、起。换完记得看一眼日志确认新版本正常启动,别换完就不管了。

5.4 我自己的习惯

用了几年 nssm,我现在装任何服务都会先做三件事:建好日志目录、设好 AppDirectory、配好 AppStdout 和 AppStderr。这三步花不了一分钟,但能省掉后面大量的“服务在跑但不知道在干嘛”的时间。nssm 本身不复杂,复杂的是程序自己的依赖和环境,把日志这扇窗留好,出问题时才有后悔药可吃。希望帮到你。

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

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

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

立即咨询