我有一个像这样的文件结构:
bots -|
|- test1 -|
|- index.js
|- activate.bat
|- token.txt
|- test2 -|
|- index.js
|- actiate.js
|- token.txt
|- run_all.bat
index.js
是要使用node
命令由NodeJS运行的文件。这两个index.js
文件都需要一个存储在token.txt
文件中的密钥。 index.js
文件读取文本文件activate.bat
就是这样:@echo off
node index.js
但是我想一次运行两个,并且只启动一个
.bat
文件,这就是run_all.bat
的所在。我试着像在
activate.bat
中一样运行每个文件,所以:@echo off
echo Starting all bots...
start /b node test1\index.js
start /b node test2\index.js
但是我得到一个错误:
PS C:\Users\Simon\Desktop\bot> ./run_all.bat
Starting all bots...
PS C:\Users\Simon\Desktop\bot> test1 running
test2 running
(node:10176) UnhandledPromiseRejectionWarning: Error: An invalid token was provided.
at Promise (C:\Users\Simon\node_modules\discord.js\src\client\rest\RESTMethods.js:34:54)
at new Promise (<anonymous>)
at RESTMethods.login (C:\Users\Simon\node_modules\discord.js\src\client\rest\RESTMethods.js:33:12)
at Client.login (C:\Users\Simon\node_modules\discord.js\src\client\Client.js:279:30)
at ReadFileContext.callback (C:\Users\Simon\Desktop\bot\test1\index1.1.js:88:12)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:235:13)
(node:4836) UnhandledPromiseRejectionWarning: Error: An invalid token was provided.
at Promise (C:\Users\Simon\node_modules\discord.js\src\client\rest\RESTMethods.js:34:54)
at new Promise (<anonymous>)
at RESTMethods.login (C:\Users\Simon\node_modules\discord.js\src\client\rest\RESTMethods.js:33:12)
at Client.login (C:\Users\Simon\node_modules\discord.js\src\client\Client.js:279:30)
at ReadFileContext.callback (C:\Users\Simon\Desktop\bot\test2\index.js:65:12)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:235:13)
(node:10176) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:4836) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:10176) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:4836) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
单独运行每个
activate.bat
时,我没有收到此错误,这是怎么回事?我的批处理命令是否以某种方式混淆了不同的token.txt
文件
最佳答案
通过使用命令START的选项/D
为启动的进程定义当前目录,可以解决主要问题。所有index.js
显然都希望文件token.txt
位于当前目录中,而当前目录是包含两个文件的目录。 Windows会默认将当前目录设置为例如双击批处理文件activate.bat
时的批处理文件目录。
@echo off
echo Starting all bots...
start "" /B /D"%~dp0test1" node index.js
start "" /B /D"%~dp0test2" node index.js
命令START将第一个双引号参数字符串解释为控制台窗口的可选标题。在不打开控制台窗口的情况下启动
node
。优良作法是始终使用命令START定义标题。在这种情况下,用""
指定的空窗口标题是一个很好的选择,因为在启动Windows GUI应用程序时也没有打开任何控制台窗口。子目录
test1
和test2
始终位于包含批处理文件run_all.bat
的目录中。因此,%~dp0
用于引用参数0的驱动器和路径,该参数是当前执行的批处理文件。这使批处理文件run_all.bat
本身独立于执行run_all.bat
时的当前目录。/
(正斜杠)是Linux / Mac上的目录分隔符。但是,由于\
用于Windows上的选项,因此应在Windows的文件/文件夹路径中使用/
(反斜杠),但从Unix移植到Windows且不适应Windows语法的应用程序除外。由于兼容性原因,用于文件/文件夹访问的Windows内核功能将所有/
替换为\
,以便在访问Windows文件系统之前自动更正路径,但是使用当前目录分隔符和Windows脚本在Windows脚本中写入文件/文件夹路径绝对更好。不依赖于Windows内核的这种自动更正。%~dp0
扩展为始终以反斜杠结尾的路径字符串。因此,在将此动态字符串与固定的文件/文件夹名称/路径连接时,不应使用其他反斜杠。否则,将在执行时串联两个\
。用于文件/文件夹访问的Windows内核功能也会自动通过\\
校正文件/文件夹引用字符串中的\
。但是最好还是避免此错误。有关更多详细信息,请参见Microsoft关于Naming Files, Paths, and Namespaces的文章。
因此,在使用参数
index.js
运行token.txt
之前,命令START现在设置包含node
和index.js
的目录。更好的解决方案是使用此批处理文件:
@echo off
echo Starting all bots...
for /F "delims=" %%I in ('dir "%~dp0index.js" /A-D-H /B /S 2^>nul') do start "" /B /D"%%~dpI" node index.js
命令FOR使用
cmd.exe /C
在单独的命令进程中运行(更确切地说,%CompSpec% /C
在后台命令行中运行:dir "C:\Users\Simon\Desktop\bot\index.js" /A-D-H /B /S 2>nul
DIR输出以处理开始的命令过程的STDOUT
由于选项
/B
以裸格式显示由于选项
/S
而具有扩展名和完整路径的文件名由于选项
/A-D-H
而导致的所有非隐藏文件中的全部(属性不是目录,也不是隐藏的)由于选项
index.js
在指定目录或任何子目录中找到文件名/S
的文件。通过重定向到设备NUL,可以抑制DIR为处理STDERR而输出的错误消息,如果找不到与这些条件匹配的任何内容,该消息将受到抑制。
阅读有关Using Command Redirection Operators的Microsoft文章,以获取
2>nul
的解释。当Windows命令解释器在执行命令FOR之前,Windows命令解释器处理此命令行时,重定向操作符>
必须在FOR命令行上使用插入符号^
进行转义,以将其解释为文字字符,该命令将在单独的命令中执行嵌入的dir
命令行进程在后台启动。带有选项
/F
的FOR捕获输出以处理启动的后台命令进程的STDOUT,并在启动的cmd.exe
终止后处理该输出。空行始终被FOR忽略,此处不会出现。默认情况下,以;
开头的行也被FOR忽略,因为分号是默认的行尾选项。 DIR输出的完整合格文件名不可能以分号开头,因此在这种情况下可以保留默认eol=;
。默认情况下,FOR将使用正常空格和水平制表符作为字符串定界符将每一行拆分为子字符串,并且仅将第一个空格/制表符分隔的字符串分配给指定的循环变量。由于文件路径中可能还包含一个或多个空格,因此在此不需要此行为。因此,使用delims=
禁用了行拆分行为,该行定义了一个空的定界符列表,从而导致始终将完整的合格文件名分配给循环变量。如上所述,FOR对DIR输出的每个文件名执行命令START。如果使用
/D"..."
指定的目录路径不带末尾或带反斜杠,则对于START而言并不重要。与第一个批处理文件解决方案相比,第二个批处理文件解决方案的主要优点很容易看出:在使用
run_all.bat
删除或添加其他目录时,不得编辑index.js
。但是请注意,并行运行太多
node
实例可能会适得其反,具体取决于index.js
中的代码。因此,扩展批处理文件以启动不超过x个node
并暂停批处理文件执行,直到一个node
实例终止自身,然后启动下一个实例,直到达到并行运行的node
实例的最大可用数量,这可能是有用的。要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
dir /?
echo /?
for /?
start /?
PS:我建议至少使用文件扩展名指定
node
,最好使用完整路径来指定PATHEXT
,以使批处理文件独立于环境变量PATH
和关于node.js - 使用批处理文件一次运行多个NodeJS项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53802705/