NSSM - the Non-Sucking Service Manager

命令行

下载

用法

nssm无需“安装” 。只需将其放置在系统上的某个位置(最好是 PATH 中的某个位置)并运行即可。

但请注意,nssm会将自身注册为事件日志消息源,这意味着从不同位置运行多个 nssm实例或不同版本可能会造成混淆。另请注意,如果您运行事件查看器,它将打开nssm可执行文件,从而阻止您覆盖它。如果您要升级**nssm ,请记住这一点 。

某些功能标明自特定版本起受支持。如果所述版本比 下载页面提供的版本更新,则可能存在已启用该功能的预发布 版本。

以下等效命令示例展示了 用于配置现有服务以匹配屏幕截图的命令 。在许多情况下,它们代表相关参数的默认值,因此是多余的。任何参数也可以使用以下命令重置为默认值:

安装服务

您可以使用nssm来安装服务。输入的命令如下:

安装程序包含多个选项卡,其中包含大量可配置参数。大多数参数都预设为nssm的默认值,因此无需离开**“应用程序”选项卡即可安装服务。

“应用程序”选项卡

您要运行的应用程序(或脚本)的路径是唯一必填字段。如果应用程序需要在特定目录中启动,您可以在“启动目录”字段中输入该目录。如果此字段留空,则默认启动目录将是包含该应用程序的目录。“参数”字段可用于指定要传递给应用程序的任何命令行参数。

下图展示了 UT2003服务器的安装过程。运行该服务的命令是 ucc server,因此在 Path 下输入 UCC.exe 的完整路径,在 Options 下输入 server

img

等效命令

单击“安装服务”即可完成服务的安装。

详细信息选项卡

详细信息选项卡列出了有关该服务的系统详细信息。

img

等效命令

登录选项卡

“登录”选项卡可用于管理将运行该服务的用户帐户。nssm 自动确保您选择的帐户具有必要的登录即服务权限。

img

等效命令

有关在命令行上配置帐户和密码的详细信息,请参阅命令行使用文档。如果需要配置空白密码,则必须 使用命令行。

依赖项

依赖项选项卡列出了服务运行之前必须启动的所有服务或服务组。

您可以输入服务名称或显示名称,每行一个。服务组名称必须以 SC_GROUP_IDENTIFIER 前缀(+ 符号)开头。

img

等效命令

进程选项卡

“进程”选项卡可用于设置应用程序的进程 优先级和 CPU 亲和性。默认情况下,应用程序将以正常优先级运行,并允许在所有 CPU 上执行。如果您希望将进程限制在可用 CPU 的子集上,请取消选中“所有处理器”,然后根据需要选择 CPU。

服务运行时,可以从 Windows 任务管理器更改进程优先级和亲和性。

img

等效命令

关机选项卡

“关闭”选项卡列出了崩溃后整理应用程序或服务正常停止时使用的各种停止方法和超时。

img

等效命令

退出操作选项卡

“退出操作”选项卡可用于调整 服务 退出时的重启限制和默认 操作。您还可以指定应用程序自动重启之间的强制延迟时间。

要为特定应用程序退出代码配置退出操作,您必须使用如下所述的注册表。

img

等效命令

“I/O”选项卡

I/O选项卡可用于指定启用I/O 重定向时使用的输入和/或输出文件。设置 “输出”“错误”通常足以捕获应用程序生成的日志消息。

按照如下所述在注册表中配置 I/O,以便更好地控制路径和访问模式。

img

等效命令

文件轮换选项卡

文件轮换选项卡可与I/O设置结合使用, 以配置文件重启时的输出文件轮换。

如果选中“替换现有的输出和/或错误文件”复选框, nssm将在启动服务时覆盖现有的输出文件。默认设置是附加到任何现有文件。如果 选中“轮换文件”复选框, nssm将在设置 I/O 重定向之前重命名现有文件。使用“限制轮换” 字段可禁用文件轮换,这些文件修改时间少于指定的秒数或小于指定的千字节数。

默认情况下,nssm仅在服务(重新)启动时执行文件轮转。要启用在服务运行时轮转已达到指定大小限制的文件,请勾选“服务运行时轮转”复选框。在线轮转会忽略任何已配置的文件使用期限限制。

危险!移动部件!在线轮转需要nssm拦截应用程序的输出并自行写入文件。复杂性的增加必然会导致故障风险的增加。

img

等效命令

“环境”选项卡

“环境”选项卡可用于指定要传递给应用程序的环境变量列表(以换行符分隔)。如果选中“替换默认环境”复选框,则指定的变量将是唯一传递给服务的变量。如果未选中该复选框(默认),则将保留服务启动时创建的环境。

img

等效命令

从命令行安装

从 2.0 版本开始,您也可以绕过 GUI,从命令行安装服务。语法如下:

请注意,实际进入服务数据库的程序是 nssm本身,因此安装服务后请勿移动或删除nssm.exe 。如果您确实希望更改**nssm.exe的路径, 可以删除并重新安装该服务,或者编辑 HKLM\System\CurrentControlSet\Services\ *servicename* \ImagePath 以反映新位置。

引用问题

nssm可以正确处理带有空格的路径,但由于命令提示符的工作方式,向其传递参数可能会很棘手。

如果应用程序的路径包含空格,则需要将其括在引号中,否则命令提示符将把路径解释为两个 参数。

如果您希望提供的选项之一包含空格,则您也需要引用该选项引用引号本身。

Isaballa Sanfelipo 建议一种从批处理文件安装 Java 应用程序的方法。

John Duffy 需要将引号传递到参数列表。

删除服务

删除服务的命令是:

img

删除服务之前会显示一个确认窗口。

img

从 2.0 版开始,您还可以从命令行删除服务:

nssm会尝试删除任何服务,而不仅仅是 nssm自身管理的服务。请尽量不要删除不该删除的服务……

 

服务关闭

nssm收到来自 Windows 服务管理器的停止命令,或检测到受监控的应用程序已退出时,它会尝试正常关闭受监控的应用程序及其所有子进程。如果应用程序的进程树未及时退出,nssm可以强制终止属于该应用程序的所有进程和子进程。

nssm可以使用四个阶段来关闭应用程序,默认情况下,它会按顺序尝试所有四个阶段。您可以(但不建议)禁用部分或全部方法。不同的应用程序对各种请求的响应会有所不同,因此,保持所有方法都处于启用状态通常是确保应用程序正常关闭的最佳方法。

首先,nssm会尝试生成 Control-C 事件并将其发送到应用程序的控制台。批处理脚本或控制台应用程序可能会拦截该事件并正常关闭。Java 应用程序通常能够良好地响应 Control-C 事件。GUI 应用程序没有控制台,因此不会响应此方法。Windows 2000 不支持此方法。

其次,nssm将枚举应用程序创建的所有窗口,并向它们发送WM_CLOSE消息。应用程序可以按照惯例,通过正常退出来响应该消息。

第三,nssm将枚举应用程序创建的所有线程并向它们发送WM_QUIT消息,如果应用程序具有线程消息队列,则会收到该消息。

作为最后的手段,nssm可以调用TerminateProcess()该函数请求操作系统强制终止应用程序。该TerminateProcess()调用无法被捕获或忽略,因此在大多数情况下,应用程序会被终止。但是,应用程序不太可能在退出之前执行任何清理操作。

要禁用上述任何方法,请创建一个整数(REG_DWORD)值 HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppStopMethodSkip ,并将其设置为以下一个或多个数字的总和。

例如,如果您知道某个应用程序没有响应 Control-C 并且没有线程消息队列,则可以将 AppStopMethodSkip设置为 5。

强烈建议不要禁用该 TerminateProcess()调用。服务停止后, nssm将退出。如果应用程序在此之前未终止,它可能会继续运行,nssm将无法再控制它。

默认情况下,nssm在尝试上述每种方法后,最多会等待 1500 毫秒,让应用程序退出。您可以根据每种方法配置超时时间,方法是 在注册表中的HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters下创建整数 (REG_DWORD) 值 ,并将其设置为所需的等待毫秒数。

请注意,超时适用于应用程序产生的所有进程,因此如果应用程序有多个子进程,则总超时时间可能比预期的要长。

 

退出时的操作

要配置nssm在应用程序退出时应采取的操作,请编辑注册表项HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppExit的默认值 。如果nssm运行时注册表中不存在该键,它将创建该键并将其值设置为Restart。将其更改为 IgnoreExit以指定要采取的操作。nssm 仅当该键不存在时才会创建它您的更改不会被覆盖。

要为特定退出代码指定不同的操作,请在AppExit键下创建一个字符串 (REG_SZ) 值,其名称与要考虑的退出代码相同。例如,要在退出代码为 0(通常表示应用程序已成功完成)时停止服务,请创建 HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppExit\0 并将其设置为Exit。查看事件日志中来自 nssm的消息,以查看应用程序返回的退出代码。

如果您的应用程序的退出代码与注册表项不对应, nssm将在决定执行什么操作时使用AppExit的默认值。

 

重启延迟

从 2.22 版本开始,nssm可以在应用程序重启之间应用强制延迟。例如,这可以用于定期运行命令(例如每小时运行一次的批处理脚本)。

要指定重启延迟,请创建一个整数(REG_DWORD)值 HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppRestartDelay ,并将其设置为两次重启之间等待的毫秒数。

服务将在等待下次重启时将其状态报告为“已暂停”。向其发送“继续”控制将暂时取消延迟并立即触发重启。

请参阅下面有关重启限制的部分,了解在配置限制和重启延迟时nssm如何工作。

 

重启节流

为避免 CPU 过度循环,如果受监控的应用程序启动后过快退出, nssm将限制服务的重启次数。默认阈值为 1500 毫秒。如需指定其他值,请创建一个整数 (REG_DWORD) 值 HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppThrottle ,并将其设置为所需的毫秒数。

首次重启将立即尝试。如果重启的应用程序在运行达到阈值毫秒数之前继续退出,nssm将暂停至少 2000 毫秒,后续每次失败的暂停时间将加倍。最长暂停时间为 256000 毫秒,约为四分钟。当服务成功运行至少阈值时间后,延迟计数器将重置。

如果您确定了服务失败的原因并采取措施解决问题,则可以向服务发送“继续”控制,该服务将显示为“已暂停”。这样,您就无需等待下一次重启尝试。

如果配置了重启延迟,而应用程序提前退出,nssm将根据配置的延迟时间和计算出的节流时间中**较长的时间来限制重启 。例如,如果您配置了 3000 毫秒的重启延迟,并且服务每次启动都失败,则第一次重启尝试将延迟 3000 毫秒,因为配置的 3000 毫秒比节流时间 0 毫秒要长。第二次尝试也将延迟 3000 毫秒;配置的 3000 毫秒同样比节流时间 2000 毫秒要长。第三次尝试将延迟 4000 毫秒;比配置的 3000 毫秒要长。

因此,如果您打算使用重启延迟来配置以少于五分钟的间隔重复的短运行服务,则应考虑降低AppThrottle的值。

 

进程优先级和 CPU 亲和性

从 2.22 版本开始,nssm可以管理受管应用程序的 CPU 亲和性和进程优先级。

默认情况下,应用程序将以正常进程优先级启动,并允许在任何 CPU 上执行。nssm 将在HKLM \System\CurrentControlSet\Services\ *servicename* \Parameters下查找 注册表项来配置应用程序启动。

如果设置了 整数(REG_DWORD)值AppPriority , nssm将把它的值解释为参数 SetPriorityClass()并以指定的优先级启动应用程序。

如果设置了 字符串 (REG_SZ) 值AppAffinity , nssm会将其解释为以逗号分隔的 CPU ID 列表,从0开始,表示应用程序可以在哪个 CPU ID 上运行。或者,也可以使用短划线分隔索引来指定 ID 范围。

亲和性字符串中只有数字、破折号和逗号有效。

例如,字符串0-2,4指定应用程序可以在系统中的第一、第二、第三和第五个 CPU 上运行。

控制台窗口

从 2.22 版本开始,nssm将默认为应用程序创建一个新的控制台窗口。这使得一些原本会失败的程序能够运行,例如那些需要读取用户输入的程序。如果不需要控制台窗口,可以通过将HKLM\System\CurrentControlSet\Services** *servicename*** \Parameters下的 整数 (REG_DWORD) 值AppNoConsole设置 为非零值来禁用它。

 

I/O重定向

nssm可以将托管应用程序的 I/O 重定向到任何能够被 打开的路径CreateFile()。如果您的应用程序需要登录到控制台,此功能可能很有用。

nssm会在**HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters**下查找 与 参数对应的键CreateFile()。所有键均为可选键。如果未指定特定流的路径,则不会重定向。如果指定了路径,但指定了其他任何值,则将采用合理的默认值。

一般来说,建议同时设置AppStdoutAppStderr以记录输出,因为应用程序可能会分别记录信息和错误消息。

可以将 stderr 和 stdout 指向同一路径,但由于nssm的限制,您必须在AppStdoutAppStderr注册表值中提供*完全相同的字符串。只有当这两个条目相同时,*nssm才能交错这两个流。

 

文件轮换

从 2.22 版本开始,如果启用了 I/O 重定向, nssm可以在启动应用程序之前轮换现有的输出文件。nssm 可以在服务运行时轮换文件。请参阅下文的在线轮换

要启用轮换,请创建一个整数(REG_DWORD)值 HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters\AppRotate 并将其设置为 1。在(重新)启动服务之前,nssm将轮换在AppStdout和/或 AppStderr中配置的文件(如果它们已经存在)。

现有文件将根据使用文件上次修改时间的模板重命名。例如,C:\Services\myservice.log 可能会被替换为C:\Services\myservice-20140114T180840.953.log

请注意,时间戳采用 ISO8601 格式,因此按名称排序的轮换文件列表将首先显示最旧的文件,并且包含毫秒部分,这样如果服务退出并在不到一秒的时间内重新启动,文件就不会丢失。

HKLM\System\CurrentControlSet\Services\ *servicename* \Parameters下的两个附加注册表设置 可用于调整nssm旋转文件的方式。

如果设置了 整数(REG_DWORD)值AppRotateSeconds , nssm将不会轮换任何上次修改时间少于 配置的秒数的文件。

如果设置了 整数 (REG_DWORD) 值AppRotateBytes , nssm将不会旋转任何小于配置字节数的文件。nssm 可以处理大小过大而无法用 32 位表示的文件,例如,如果您认为日志文件大小达到 4GB 没问题,但再大就太大了。AppRotateBytesHigh**的**值将被解释为 64 位大小的高位部分。

如果同时设置了AppRotateSecondsAppRotateBytes(High) , nssm将要求文件轮换时同时满足这两个条件。

 

在线轮换

如果将整数 (REG_DWORD) 值AppRotateOnline设置为 1,nssm可以在服务运行时轮换已达到配置文件大小限制的文件。在线轮换时, AppRotateSeconds的值 将被忽略,但在服务(重新)启动之前,该值仍会应用于轮换。

如果未设置AppRotate ,则忽略AppRotateOnline 。

启用在线轮转后,nssm会读取应用程序的标准输出 (stdout) 和/或标准错误 (stderr),并自行写入输出文件。与简单的 I/O 重定向相比,这样做会增加一定程度的复杂性,因此不应用于不需要 I/O 重定向的服务。尽管nssm会尝试妥善处理 I/O 错误,但如果出现问题,应用程序的输出可能会丢失,直到服务重新启动为止。 有关nssm如何处理 I/O 重定向的更多详细信息, 请参阅技术讨论

 

按需轮换

nssm可以按需轮换输出文件,无论它们是否已达到配置的大小限制。要为服务请求文件轮换,请发送用户定义的服务控制码 128 或运行以下 命令

按需轮转的一个限制是,实际的文件重命名操作要等到应用程序读取下一行输入后才会进行。因此,发出轮转请求和轮转执行之间可能会有相当长的延迟,具体取决于应用程序的冗长程度。

即使未配置AppRotateBytes (即服务运行时不旋转文件),按需旋转功能仍可正常工作。但是,除非同时配置了AppRotateAppRotateOnline,否则此功能无效。

 

I/O 重定向技术细节

在查看服务如何处理 I/O 时,需要考虑三种情况。

无重定向

在最简单的情况下,nssm未配置任何 I/O 重定向。它将启动应用程序,并将 stdin、stdout 和 stderr 连接到控制台实例。如果该服务在 LOCALSYSTEM 帐户下运行,并配置为与桌面交互,您可能能够直接查看输出。

I/O 重定向;在线轮换已禁用

如果 stdout 和/或 stderr 被重定向,并且在线轮转被禁用, nssm将调用CreateFile()为每个 I/O 流打开一个句柄,然后调用 将该DuplicateHandle()句柄的副本设置到STARTUPINFO传递给 的数据结构 中CreateProcess()。因此,应用程序将使用打开的文件句柄运行,而nssm本身没有打开的句柄。

I/O 重定向;已启用在线轮换

这种情况是三种情况中最复杂的,因此发生错误的风险也最大,可能会导致应用程序输出丢失。

nssm首先CreateFile()像上例一样调用 。然后,它调用CreatePipe()来打开一个匿名管道。管道的读取端和输出文件的句柄会被传递给一个执行实际写入操作的新线程。管道的写入端被复制并DuplicateHandle()传递给 CreateProcess()。因此,应用程序将使用管道一端的打开句柄运行,而nssm将使用管道另一端的句柄和输出文件的句柄运行。

写入线程运行一个简单的循环,其中它从管道(即应用程序的输出)读取数据到缓冲区,ReadFile() 然后用 将该缓冲区的内容写入输出文件 WriteFile()。如果文件达到配置的大小限制,该线程将写入到下一个换行符,关闭其输出句柄,旋转文件并打开新的句柄以继续写入新文件。

nssm收到按需旋转请求时,它会设置一个标志,指示写入线程在下一次 ReadFile()调用完成后执行旋转,无论文件大小如何。由于 ReadFile()nssm 会阻塞执行直到读取内容,因此 在应用程序生成下一行输出之前, nssm实际上不会真正开始旋转文件。

nssm不知道应用程序的输出是 Unicode 还是 ANSI,因此在将第一个数据写入文件或进行旋转之前,它会调用 nssmIsTextUnicode()来尝试确定正在使用的文本编码。如果(看起来)是 Unicode,nssm 会在新文件的开头写入一个 UTF-16 字节顺序标记,以便使用文本编辑器打开时能够正确读取。

如果 stdout 和 stderr 都被重定向到单独的文件, nssm将为每个文件生成一个写入线程。nssm 将处理以Unicode写入 stdout 并以 ANSI 写入 stderr 的应用程序 - 或反之亦然 - 如果您不幸(或邪恶)运行了一个这样的应用程序。

从上面可以清楚地看出,在线轮换存在许多缺陷。nssm 尝试妥善处理 I/O 过程中的任何问题,但为了安全起见,您应该考虑不要使用在线轮换,除非您的输出量太大而您别无选择。

 

环境变量

从 2.11 版开始,nssm遵循 srvany支持的AppEnvironment注册表值。要指定传递给受监控应用程序的环境变量列表,请创建一个多值字符串 (REG_MULTI_SZ) 值 HKLM\System\CurrentControlSet\Services** *servicename** \Parameters\AppEnvironment ,其中每个条目的格式为KEY=VALUE*。

如果您只希望环境变量KEY存在,但=符号是必需的,则可以省略VALUE如果指定的环境变量无效,服务将无法运行!

从 2.19 版本开始,nssm还遵循 AppEnvironmentExtra注册表值,该值应与*AppEnvironment具有相同的格式。在AppEnvironmentExtra**中设置的环境变量 将被添加*到服务的默认环境中。

为了与srvany兼容, AppEnvironment中指定的环境变量将替换服务启动时系统设置的环境变量。这可能并非您想要的效果,请改用 AppEnvironmentExtra