首页 > 解决方案 > 启动节点应用程序的批处理脚本在执行后消失

问题描述

这个用于工作的节点应用程序以批量启动脚本启动。启动后 cmd 窗口停留在那里,它打开了正确的端口,但它总是启动浏览器太快,所以显示 404。npm 启动后,您可以刷新页面,它启动正常。

@echo off
@setlocal

set NODE_HOME=%~dp0/nodejs
set PATH=%NODE_HOME%;%PATH%

call npm install
start http://localhost:8090/
call npm start

我想稍微调整一下,让它在启动浏览器之前等待几秒钟。所以我想我只需要在 npm start 向 CLI 输出“准备工作”之后打开 localhost。但是该命令实际上永远不会“完成”,因此永远不会执行打开的 localhost。我试图这样解决它:

@echo off
@setlocal

SET NODE_HOME=%~dp0/nodejs
SET PATH=%NODE_HOME%;%PATH%

CALL npm install
START /B CMD /C CALL openlocalhost8090.cmd
CALL npm start

这就是 openlocalhost.cmd 的样子:

@echo off

TIMEOUT /T 5 /NOBREAK >NUL
START http://localhost:8090/

它实际上启动良好,它在执行 npm start 的同时在后台等待,因此浏览器启动时没有 404 并且应用程序运行良好!但是现在我再次对其进行测试,启动浏览器后 cmd 窗口消失了。这很不方便,因为我仍然希望查看日志输出并能够通过关闭 cmd 窗口来停止服务器。原来的剧本就是这样。我需要进入任务管理来找到现在停止它的进程。

如何解决此问题以使 cmd 窗口保持活动状态?

另外,有没有更好的方法来处理这个 404“错误”?(我喜欢 bash,我可以使用open localhost:8090 & npm start并完成!)

编辑:在@Mofi 的建议之后,这就是我想出的:

@echo off
@setlocal

SET NODE_HOME=%~dp0nodejs
SET PATH=%NODE_HOME%;%PATH%

CALL "%NODE_HOME%\npm.cmd" install
START /B CMD /K CALL openlocalhost8090.cmd
CALL "%NODE_HOME%\npm.cmd" start

我仍然用 openlocalhost8090.cmd 做下标,因为与@Mofi 声称的相反,只要将 open localhost 和调用 npm start 放在一起就可以解决我的问题,但它没有。将所有内容直接放在彼此之下是第一个脚本的问题以及我想要解决的问题。浏览器启动太快,所以它在 npm 启动之前 404。如果这不是你的意思@Mofi,那么我很抱歉,但我没有找到你的答案写得很清楚。

然而, CMD 之后的 /K 标志阻止了 cmd 窗口关闭并解决了这个问题,所以谢谢你!

标签: node.jsbatch-filecmd

解决方案


1.完整的批处理文件执行环境定义

使用 just@setlocal会导致创建现有环境变量列表的副本,将当前目录路径推送到堆栈以及命令扩展和延迟扩展的状态,而不会更改命令扩展和延迟环境变量扩展的状态。因此,该命令无法完整定义批处理文件的执行环境。执行环境仍然取决于为命令扩展定义的内容和批处理文件之外的延迟扩展,这通常对任何批处理文件都不利。

定义执行环境的完美命令行是这个批处理文件:

setlocal EnableExtensions DisableDelayedExpansion

2. 使用批处理文件路径更正变量定义

命令行set NODE_HOME=%~dp0/nodejs不好是因为

  • \是 Windows 上的目录分隔符,而不是/Linux/Mac 上的目录分隔符,因为它可以在有关命名文件、路径和命名空间的 Microsoft 文档中阅读, 以及
  • %~dp0扩展为始终以反斜杠结尾的路径,因此在将完整的批处理文件路径与文件/文件夹名称或通配符模式连接时不应添加额外的反斜杠,Windows 以后每次使用包含现在在\\ 里面
  • 命令SET的整个参数字符串不包含在双引号中,这导致此命令行不仅仅将文件夹路径分配给NODE_HOME批处理文件的完整路径上的环境变量,还包含一个或多个&类似于C:\Temp\Development & Test解释的文件夹路径通过cmd.exe在双引号参数字符串之外作为命令运算符,使用 Windows 批处理文件在单行上详细解释了多个命令

确保启用命令扩展并禁用延迟环境变量扩展后,完美的命令行如下:

set "NODE_HOME=%~dp0nodejs"

批处理文件完整路径中的 & 符号在这里被解释为命令SET的双引号参数字符串中的文字字符。

在编写批处理文件时,命令行在 Windows 命令处理器解析并替换所有环境变量、循环变量和批处理文件参数引用后的外观非常重要,而不是命令行在批处理文件中的写入方式。此命令行不包含&批处理文件,但它可以包含&在替换%~dp0为批处理文件的完整路径后执行命令行。

cmd.exe可以通过从打开的命令提示符窗口中运行批处理文件来查看命令行在解析后的外观,@echo off并暂时删除或注释掉以显示最终执行的命令行。

3.正确修改本地环境变量PATH

set PATH=%NODE_HOME%;%PATH%再次不好,因为如果分配给环境变量NODE_HOME或环境变量的字符串PATH包含&符号,则会导致未定义的行为。完美且安全的命令行(在有效PATH字符串上)将是:

set "PATH=%NODE_HOME%;%PATH%"

4. 引用具有完全限定文件名的可执行文件和脚本

始终最好在批处理文件中引用可执行文件和脚本,并在众所周知的情况下使用完整的限定文件名,而不仅仅是文件名,因为在这种情况下cmd.exe,不需要在当前目录和本地环境变量中列出的所有目录中搜索文件对于具有在本地环境变量PATH中列出的扩展名的文件。PATHEXT

请查看关于“X 未被识别为内部或外部命令、可运行程序或批处理文件”的原因是什么?详情。

引用具有完全限定文件名的可执行文件和脚本的批处理文件也可以在PATH安装程序或用户以某种方式损坏的情况下工作,并且如果创建的文件(主要是批处理)文件的文件名与Windows 命令中使用的相同批处理文件,但偶然发现cmd.exe而不是%SystemRoot%\System32.

因此,将批处理文件npm.cmd存储在nodejs批处理文件目录的子目录中,最好将其用作最后三个命令行的替换:

call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
start "" "http://localhost:8090/"

5.不需要额外的批处理文件

目前尚不清楚为什么另一个命令处理器实例开始与处理批处理文件的实例并行运行,该cmd.exe实例在调用批处理文件后npm.cmd使用参数install处理另一个批处理文件,该批处理文件运行%SystemRoot%\System32\timeout.exe(没有文件路径和文件扩展名)等待五秒钟,然后启动默认值以本地 url 作为参数作为单独进程的 Internet 浏览器,导致第二个启动的实例cmd.exe自行终止。

在处理完带参数后,使用npm.cmd参数调用start并以本地 url 作为参数启动默认互联网浏览器就足够了。npm.cmdstart

所以整个批处理文件可能是:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
start "" "http://localhost:8090/"

这可能会call "%NODE_HOME%\npm.cmd" start导致将应用程序作为单独的进程或服务启动,这需要一些时间才能完全初始化,因此必须等待几秒钟才能使用本地 url 启动 Internet 浏览器,这需要启动的应用程序/服务是已经在运行了。在这种情况下,批处理文件应该是:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul
start "" "http://localhost:8090/"

根据发布的信息,它看起来并非如此,但是如果处理批处理文件的call "%NODE_HOME%\npm.cmd" start结果由于在到达批处理文件末尾之前没有选项cmd.exe的命令而自行终止,或者调用的批处理文件的处理永远不会完成,因为正在等待已启动但不会自行终止的可执行文件的自终止,批处理文件应为:exit/Bcmd.exe

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
start "Launch browser delayed" /MIN %ComSpec% /C %SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul & start "" "http://localhost:8090/"
call "%NODE_HOME%\npm.cmd" start

在任何情况下都不需要额外的批处理文件。

6. 批处理文件执行完成后保持命令处理器运行

%ComSpec% /c "Full qualified batch file name"Windows在双击批处理文件时隐式执行,并将批处理文件目录设为cmd.exe. 在命令提示符窗口中运行的帮助输出cmd /?说明该选项/C用于运行命令行并在完成此命令行的执行后关闭。 cmd.exe此处不需要此默认行为。命令处理器应在批处理文件执行后继续运行,这需要cmd.exe以选项/K和完全限定的批处理文件名开头。

因此,需要在 Windows 桌面或 Windows 开始菜单或其他地方创建一个快捷方式文件 (.lnk) 文件,并将其固定到 Windows 任务栏,其中包含以下属性:

目标: %SystemRoot%\System32\cmd.exe /K“完整的批处理文件名”
开始于: “批处理文件夹的完整路径”

属性Target也可以是:

%ComSpec% /K "Full qualified batch file name"

ComSpec是一个系统环境变量,它甚至可以单独使用,cmd.exe并且必须始终%SystemRoot%\System32\cmd.exe按照 Windows 默认值定义。

在快捷方式文件的属性中,还可以配置cmd.exe通过此快捷方式运行时打开的控制台窗口的行数和列数、字体、文本前景色和背景色等等。甚至可以通过按下此键(或组合键)定义要启动的快捷键cmd.exe,以便在任何应用程序中处理批处理文件。


推荐阅读