Project Icon

node-windows

Node.js脚本作为Windows服务的管理工具

node-windows是一个用于在Windows环境下管理Node.js应用程序的工具库。它能将Node.js脚本作为Windows后台服务安装、启动、停止和卸载,适用于生产环境。该库提供服务管理、事件日志记录和提升权限运行命令等功能,无需使用原生模块或额外安装开发工具。node-windows还具有智能服务重启机制和灵活配置选项,简化了Node.js应用在Windows上的部署和管理。

node-windows

NPM 版本 NGN 依赖

这个库可用于在生产环境中将 Node 脚本安装/启动/停止/卸载为 Windows 后台服务。这不是用于开发应用程序的工具,而是用于发布应用程序的工具。

如果需要支持其他操作系统,请查看 node-macnode-linux

如果需要帮助,可以在 Twitter 上联系我 @goldglovecb

赞助商


 

无法赞助?
考虑提名 @coreybutler 获得 Github 之星

概述

node-windows 提供以下功能:

  • 服务管理:将 Node.js 脚本作为本地 Windows 服务运行。包括监控功能。
  • 事件日志:在事件日志中创建日志。
  • 命令
    • 提升权限:以提升的权限运行命令(可能会提示用户接受)
    • Sudo:以 sudo 权限运行 exec 命令。
    • 识别管理员权限:确定当前用户是否具有管理员权限。
    • 列出任务:列出正在运行的 Windows 任务/服务的方法。
    • 终止任务:终止特定 Windows 服务/任务(通过 PID)的方法。

安装

推荐使用 npm 安装 node-windows,并使用全局标志:

npm install -g node-windows

然后,在项目根目录运行:

npm link node-windows

然而,也可以不使用全局标志直接将 node-windows 安装到项目根目录中。 关于为什么不推荐这种方法的更多详细信息,请参阅本自述文件的其他部分。

无原生模块

在 Windows 上使用原生 Node 模块可能很麻烦。大多数原生模块不以二进制格式分发。 相反,这些模块依赖于 npm 来构建项目,使用 node-gyp。 这意味着开发人员需要在系统上安装 Visual Studio(可能还需要其他软件), 仅仅是为了安装一个原生模块。这是可移植的,但很痛苦...主要是因为 Visual Studio 本身就超过 2GB。

node-windows 不使用原生模块。 有一些二进制/可执行文件实用程序,但运行更复杂任务所需的一切 都已打包并以随时可用的格式分发。因此,不需要 Visual Studio...至少对于这个模块来说不需要。


Windows 服务

node-windows 有一个实用工具可以将 Node.js 脚本作为 Windows 服务运行。请注意,与所有 Windows 服务一样,创建服务需要管理员权限。要使用 node-windows 创建服务,请准备一个如下的脚本:

var Service = require('node-windows').Service;

// 创建一个新的服务对象
var svc = new Service({
  name:'Hello World',
  description: 'nodejs.org 示例 Web 服务器。',
  script: 'C:\\path\\to\\helloworld.js',
  nodeOptions: [
    '--harmony',
    '--max_old_space_size=4096'
  ]
  //, workingDirectory: '...'
  //, allowServiceLogon: true
});

// 监听 "install" 事件,该事件表示
// 进程作为服务可用。
svc.on('install',function(){
  svc.start();
});

svc.install();

上面的代码创建了一个新的 Service 对象,提供了一个漂亮的名称和描述。 script 属性指定了应作为服务运行的 Node.js 脚本。运行此脚本后, 它将在 Windows 服务实用程序中可见。

Windows 服务

Service 对象会发出以下事件:

  • install - 当脚本作为服务安装时触发。
  • alreadyinstalled - 如果脚本已知是一个服务时触发。
  • invalidinstallation - 如果检测到安装但缺少必需文件时触发。
  • uninstall - 卸载完成时触发。
  • alreadyuninstalled - 当请求卸载但不存在安装时触发。
  • start - 新服务启动时触发。
  • stop - 服务停止时触发。
  • error - 在某些情况下发生错误时触发。

在上面的例子中,脚本监听 install 事件。由于此事件在服务安装完成时触发,因此可以安全地启动服务。

由 node-windows 创建的服务类似于 Windows 上运行的大多数其他服务。它们可以通过 Windows 服务实用程序、NET STARTNET STOP 命令启动/停止,甚至可以使用 sc 实用程序进行管理。

命令行选项

可能需要为脚本指定命令行开关。您可以通过在服务配置中设置 scriptOptions 来实现这一点:

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  scriptOptions: '-c C:\\path\\to\\somewhere\\special -i'
});

环境变量

有时您可能希望在创建服务时为服务提供静态数据。您可以通过在服务配置中设置环境变量来实现这一点,如下所示:

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  env: {
    name: "HOME",
    value: process.env["USERPROFILE"] // 服务现在能够访问创建它的用户的主目录
  }
});

您还可以提供一个数组来设置多个环境变量:

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  env: [{
    name: "HOME",
    value: process.env["USERPROFILE"] // 服务现在能够访问创建它的用户的主目录
  },
  {
    name: "TEMP",
    value: path.join(process.env["USERPROFILE"],"/temp") // 在用户的主目录中使用临时目录
  }]
});

Node 可执行文件路径

有时您可能想指定一个特定的 node 可执行文件来运行您的脚本。您可以通过在服务配置中设置 execPath 来实现这一点,如下所示:

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  execPath: 'C:\\path\\to\\specific\\node.exe'
});

用户账户属性

如果您需要指定特定用户或特定凭据来管理服务,以下属性可能会有所帮助。

user 属性是一个具有三个键的对象:domainaccountpassword。 这可用于识别服务库应使用哪个用户来执行系统命令。 默认情况下,域设置为本地计算机名,但可以被 Active Directory 或 LDAP 域覆盖。例如:

app.js

var Service = require('node-windows').Service;

// 创建一个新的服务对象
var svc = new Service({
  name:'Hello World',
  script: require('path').join(__dirname,'helloworld.js'),
  //, allowServiceLogon: true 
});

svc.logOnAs.domain = 'mydomain.local';
svc.logOnAs.account = 'username';
svc.logOnAs.password = 'password';
...

如果您希望服务模块以特定用户身份运行命令,必须明确定义账户和密码。默认情况下,它将使用启动进程的用户账户运行(即谁启动了 node app.js)。

如果您想指示 winsw 允许服务账户登录,请指定 allowServiceLogon: true。默认情况下这是禁用的,因为一些用户在不使用服务登录的情况下运行时遇到了问题。

另一个属性是 sudo。这个属性有一个名为 password 的单一属性。通过提供这个,服务模块将尝试使用启动进程的用户账户和该账户的密码来运行命令。这应该只用于具有管理权限的账户。

app.js

var Service = require('node-windows').Service;

// 创建一个新的服务对象
var svc = new Service({
  name:'Hello World',
  script: require('path').join(__dirname,'helloworld.js')
});

svc.sudo.password = 'password';
...

依赖其他服务

该服务还可以被设置为依赖于其他 Windows 服务。

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  dependsOn: ["serviceA"]
});

清理:卸载服务

卸载先前创建的服务在语法上与安装类似。

var Service = require('node-windows').Service;

// 创建一个新的服务对象
var svc = new Service({
  name:'Hello World',
  script: require('path').join(__dirname,'helloworld.js')
});

// 监听 "uninstall" 事件,以便我们知道何时完成。
svc.on('uninstall',function(){
  console.log('卸载完成。');
  console.log('服务是否存在:',svc.exists);
});

// 卸载服务。
svc.uninstall();

卸载过程只删除特定于进程的文件。它不会删除您的 Node.js 脚本!

是什么让 node-windows 服务与众不同?

很多方面!

长时间运行的进程和监控:

Windows 服务的内置服务恢复功能相当有限,且无法从代码中轻松配置。因此,node-windows 创建了一个 Node.js 脚本的包装器。这个包装器负责以智能和可配置的方式重启失败的服务。例如,如果您的脚本因未知错误而崩溃,node-windows 将尝试重启它。默认情况下,这每秒发生一次。然而,如果脚本存在致命缺陷导致反复崩溃,这会给系统带来不必要的开销。node-windows 通过增加重启间隔时间并限制最大重启次数来处理这种情况。

更智能的重启,不会压垮您的服务器: 使用默认设置时,node-windows 每次需要重启脚本时会将等待间隔增加 25%。在默认设置(1 秒)下,第一次重启尝试在 1 秒后发生。第二次在 1.25 秒后发生。第三次在 1.56 秒后发生(1.25 增加 25%),依此类推。初始等待时间和增长率都是可以传递给新 Service 的配置选项。例如:

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\helloworld.js',
  wait: 2,
  grow: .5
});

在这个例子中,等待期将从 2 秒开始,并增加 50%。因此,第二次尝试将在 3 秒后进行,而第四次将在 4.5 秒后进行。

别自己造成 DOS 攻击!

对于有问题的脚本,重复的循环可能会无休止地进行下去。为了处理这种情况,node-windows 支持两种类型的限制。使用 maxRetries 可以限制最大重启尝试次数。默认情况下,这是无限的。将其设置为 3 将告诉进程在失败 3 次后不再重启进程。另一个选项是 maxRestarts,它限制在 60 秒内尝试重启的次数。例如,如果将其设置为 3(默认值),并且进程反复崩溃/重启,node-windows 将在 60 秒窗口内的第 3 个循环后停止重启尝试。这两个配置选项都可以像设置 waitgrow 一样进行设置。

最后,如果你希望脚本在出错退出时重启,可以将名为 abortOnError 的属性设置为 true

服务是如何创建的

node-windows 使用 winsw 工具为每个部署为服务的 Node.js 脚本创建一个唯一的 .exe 文件。系统会创建一个名为 daemon 的目录,并在其中放置 myappname.exemyappname.xml。XML 文件是可执行文件的配置。此外,winsw 会在此目录中为自己创建一些日志(可在事件日志中查看)。

myappname.exe 文件启动 node-windows 包装器,负责监控和管理脚本。由于此文件是 node-windows 的一部分,移动 node-windows 目录可能会导致 .exe 文件无法找到 Node.js 脚本。但是,如果按照推荐的安装说明全局安装 node-windows,这应该不会成为问题。

所有这些特定于守护进程的文件都创建在名为 daemon 的子目录中,该子目录在保存 Node.js 脚本的同一目录中创建。卸载服务将删除这些文件。

事件日志记录

使用 node-windows 创建的服务有两个事件日志,可以通过 Windows 事件查看器查看。名为 myappname.exe 的日志源为可执行文件提供基本日志记录。它可用于查看整个服务何时启动/停止或出现错误。第二个日志以您的服务名称命名(例如 My App Name),由 node-windows 监视器使用。可以使用 node-windows 事件日志记录从 Node.js 脚本写入此日志。


事件日志记录

v0.1.0 版本开始,新增了一个_非 C++_ 的事件日志记录工具。此工具可以写入事件日志,使您的日志在事件查看器中可见。它在底层使用 eventcreate

要创建一个日志记录器:

var EventLogger = require('node-windows').EventLogger;

var log = new EventLogger('Hello World');

log.info('基本信息。');
log.warn('注意!');
log.error('出错了。');

看起来类似于:

Event Logging in node-windows

通过 node-windows 事件日志记录还可以使用一些不太常用的选项。

log.auditSuccess('AUser 登录成功');
log.auditFailure('AUser 登录失败');

每种日志类型(info、warn、error、auditSuccess 和 auditFailure)方法可以选择接受两个额外的参数,包括_代码_和_回调_。默认情况下,如果没有另外指定,事件代码为 1000。要为日志消息提供自定义事件代码并将该消息写入控制台,可以使用以下代码:

注意: 看起来 eventcreate 只支持 <=1000 的自定义 ID。

log.info('发生了一些不同的事情!', 700, function(){
  console.log('发生了一些不同的事情!');
});

默认情况下,所有事件日志都属于 APPLICATION 范围。但是,也可以使用 SYSTEM 日志。要做到这一点,必须向新日志传递一个配置对象:

var EventLogger = require('node-windows').EventLogger;
var log = new EventLogger({
  source: '我的事件日志',
  eventLog: 'SYSTEM'
});

可以通过在创建服务时禁用来抑制包装器产生的警告事件日志。默认情况下,警告日志是启用的。

var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  disableWarningLogs: true,
});

命令

node-windows 附带了几个命令,用于简化 MS Windows 上的任务。

elevate

Elevate 类似于 Linux/Mac 上的 sudo。它尝试将当前用户的权限提升到本地管理员。使用这个不需要密码,但需要当前用户拥有管理员权限。如果没有这些权限,命令将失败并显示 访问被拒绝 错误。

在启用了 UAC 的系统上,这可能会提示用户允许继续:

UAC 提示

语法

elevate(cmd[,options,callback])

  • cmd:要以提升的权限执行的命令。这可以是任何在命令行中输入的字符串。
  • options(可选):任何将传递给 require('child_process').exec(cmd,<OPTIONS>,callback) 的选项。
  • callback(可选):传递给 require('child_process').exec(cmd,options,<CALLBACK>) 的回调函数。

sudo

Sudo的行为类似于Linux/Mac上的sudo命令。与_elevate_不同,它需要密码,但不会提示用户确认是否继续执行。与_elevate_相似,这仍然需要用户具有管理员权限,否则命令将失败。它与_elevate()_的主要区别在于提示方式。

语法:

sudo(cmd,password[,options,callback])

  • cmd:要以提升权限执行的命令。可以是在命令行中输入的任何字符串。
  • password:用户密码
  • options(可选):将传递给require('child_process').exec(cmd,<OPTIONS>,callback)的任何选项。
  • callback(可选):传递给require('child_process').exec(cmd,options,<CALLBACK>)的回调函数。

isAdminUser

这个异步命令用于确定当前用户是否具有管理员权限。它向回调函数传递一个布尔值,如果用户是管理员则返回true,否则返回false

示例

var wincmd = require('node-windows');

wincmd.isAdminUser(function(isAdmin){
  if (isAdmin) {
    console.log('该用户具有管理员权限。');
  } else {
    console.log('不是管理员');
  }
});

list

list方法查询操作系统以获取正在运行的进程列表。

var wincmd = require('node-windows');

wincmd.list(function(svc){
  console.log(svc);
},true);

这将返回一个正在运行的进程数组。在上面的示例中提供可选的true参数可以获得详细输出。输出内容取决于操作系统版本。以下是Windows 8计算机上详细输出的示例。

[{
  ImageName: 'cmd.exe',
  PID: '12440',
  SessionName: 'Console',
  'Session#': '1',
  MemUsage: '1,736 K',
  Status: 'Unknown',
  UserName: 'Machine\\Corey',
  CPUTime: '0:00:00',
  WindowTitle: 'N/A'
},{
  ImageName: 'tasklist.exe',
  PID: '1652',
  SessionName: 'Console',
  'Session#': '1',
  MemUsage: '8,456 K',
  Status: 'Unknown',
  UserName: 'Machine\\Corey',
  CPUTime: '0:00:00',
  WindowTitle: 'N/A'
}]

常规(非详细)输出通常提供ImageNamePIDSessionNameSession#MemUsageCPUTime

kill

此方法将通过PID终止进程。

var wincmd = require('node-windows');

wincmd.kill(12345,function(){
  console.log('进程已终止');
});

在此示例中,进程ID为12345的进程将被终止。需要注意的是,执行此node脚本的用户账户可能需要管理员权限。

故障排除

如果您在使用示例时遇到问题,请查看TESTS.md文件。

如果遇到_invalidinstallation_事件,请检查安装期间创建的daemon目录,确保.exe.xml文件存在。在某些情况下,主要是在卸载过程中,进程可能会暂时锁定日志文件,阻止Windows删除它。在这种情况下,只需再次运行卸载即可。大多数情况下,这将解决问题。如果问题仍然存在,请在重新安装之前手动删除daemon目录。

致谢

许多贡献者为项目提交了功能,并在我忙碌时帮助承担工作。我非常感谢他们的帮助。

特别感谢@arthurblake,他的修改终于被添加进来。感谢@hockeytim11,他帮助整理和更新了许多未解决的问题,并开始为其他node-*库提供支持。

许可证

winsw和sudowin的版权归各自所有者所有。winsw以MIT许可证分发。sudowin以BSD许可证分发。

所有其他脚本的版权归Corey Butler所有,使用MIT许可证。

(MIT许可证)

版权所有 (c) 2013 Corey Butler

特此免费授予任何获得本软件副本和相关文档文件("软件")的人不受限制地处理本软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,并允许向其提供本软件的人这样做,但须符合以下条件:

上述版权声明和本许可声明应包含在本软件的所有副本或实质性部分中。

本软件按"原样"提供,不提供任何形式的明示或暗示担保,包括但不限于对适销性、特定用途适用性和非侵权性的担保。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,均由软件或软件的使用或其他交易引起或与之相关。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号