node.js - 启动节点应用程序的批处理脚本在执行后消失
问题描述
这个用于工作的节点应用程序以批量启动脚本启动。启动后 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 窗口关闭并解决了这个问题,所以谢谢你!
解决方案
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.cmd
start
所以整个批处理文件可能是:
@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
/B
cmd.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
,以便在任何应用程序中处理批处理文件。
推荐阅读
- python - 来自谷歌示例代码错误的 pub_sub 操作缺少 1 个必需的位置参数:“回调”
- sql-server - SQL - 使用日期范围临时表和具有开始/结束合同日期的客户列表(第二个临时表)执行计数语句
- tensorflow - Tensorflow 未检测到 GPU - 添加可见 gpu 设备:0
- laravel - Laravel 中的断路取决于文件中定义的位置
- mvvm - 使用 MVVM (Xamarin.Froms ListView) 时是否应同时设置 ItemSource 和 BindingContext?
- javascript - Get selected check boxes values from table using Java script
- javascript - 渲染后如何替换角度组件标签?
- jmeter - Influxdb - 配置文件的 [graphite] 和 [http] 中的绑定地址之间的区别
- python - 满足一定数量(条件)时如何对列的子集求和
- r - 如何为特定行重新编码多个值 tidyverse