Запуск нескольких проектов NodeJS одновременно с командным файлом - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть такая файловая структура:

bots -|
      |- test1 -|
                |- index.js
                |- activate.bat
                |- token.txt

      |- test2 -|
                |- index.js
                |- actiate.js
                |- token.txt

      |- run_all.bat

index.js - это файлы, которые должны быть запущены в NodeJS с помощью команды node.Для обоих файлов 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 файлы

1 Ответ

0 голосов
/ 17 декабря 2018

Основная проблема может быть решена с помощью опции /D команды START , чтобы определить текущий каталог для запущенных процессов.Все 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, поскольку окно консоли вообще не открывается.

Подкаталоги test1 и test2 всегдав каталоге, содержащем командный файл run_all.bat.По этой причине %~dp0 используется для ссылки на диск и путь аргумента 0, который является текущим исполняемым пакетным файлом.Это делает пакетный файл run_all.bat сам по себе независимым от текущего каталога при выполнении run_all.bat.

/ (косая черта) является разделителем каталогов в Linux / Mac.Но \ (обратная косая черта) следует использовать в Windows в путях к файлам / папкам, поскольку / используется для параметров в Windows, за исключением приложений, перенесенных из Unix в Windows без адаптации к синтаксису Windows.Функции ядра Windows для доступа к файлам / папкам заменяют все / на \ для автоматического исправления путей перед доступом к файловым системам Windows по соображениям совместимости, но определенно лучше записывать пути файлов / папок в сценариях Windows с текущим разделителем каталогов ине зависит от этого автоматического исправления ядра Windows.

%~dp0 расширяется до строки пути, всегда заканчивающейся обратной косой чертой.Поэтому не следует использовать дополнительную обратную косую черту при объединении этой динамической строки с фиксированным именем файла / папки / пути.В противном случае было бы два \ последовательно на исполнение.Функции ядра Windows для доступа к файлам / папкам также автоматически корректируются \\ в строке, ссылающейся на файл / папку, по \.Но, опять же, лучше избежать этой ошибки.

Подробнее см. Статью Microsoft о Именовании файлов, путей и пространств имен .

Команда So START устанавливает теперь каталог, содержащий index.js и token.txt перед запуском 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.

TВывод сообщения об ошибке DIR для обработки STDERR при обнаружении чего-либо, соответствующего этим критериям, подавляется путем перенаправления на устройство NUL .

.Статья Microsoft о Использование операторов перенаправления команд для объяснения 2>nul.Оператор перенаправления > должен быть экранирован с помощью символа вставки ^ в командной строке FOR , чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , котораявыполняет встроенную командную строку dir в отдельном командном процессе, запущенном в фоновом режиме.

FOR с опцией /F захватывает выходные данные для обработки STDOUT запущенного фонового командного процесса и обрабатывает эти выходные данные после завершения запуска cmd.exe.Пустые строки всегда игнорируются FOR , которых здесь нет.Строки, начинающиеся с ;, по умолчанию также игнорируются FOR , поскольку точка с запятой является опцией конца строки по умолчанию.Невозможно, чтобы полное имя файла, выводимое DIR , начиналось с точки с запятой, и поэтому в этом случае можно сохранить значение по умолчанию eol=;. FOR будет по умолчанию разделять каждую строку на подстроки с использованием обычного пробела и горизонтальной табуляции в качестве разделителей строк и назначать только первую строку с пробелом / символ табуляции для указанной переменной цикла.Такое поведение здесь нежелательно, поскольку путь к файлу может содержать также один или несколько пробелов.Поэтому поведение разделения строк отключается с помощью delims=, который определяет пустой список разделителей, в результате чего всегда получается полное полное имя файла, присвоенное переменной цикла.

FOR выполняется для каждого вывода имени файла DIR команда START , как описано выше.Для START не имеет значения, если путь к каталогу, указанный в /D"...", не имеет или имеет обратную косую черту в конце.

Основное преимущество этого второго решения для пакетного файла по сравнению с первымможно легко увидеть: run_all.bat нельзя редактировать при удалении или добавлении дополнительных каталогов с помощью index.js.

Но имейте в виду, что слишком большое количество параллельных node экземпляров может привести к обратным результатам в зависимости от того, какой код в index.js делает.Поэтому может быть полезно расширить пакетный файл, чтобы он начинал не более чем x node, и останавливать выполнение пакетного файла до тех пор, пока один экземпляр node не завершит сам себя, прежде чем запускать следующий экземпляр при достижении максимально допустимого числа параллельных операций.node экземпляров.

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.

  • dir /?
  • echo /?
  • for /?
  • start /?

PS: предлагаю уточнитьnode по крайней мере с расширением файла и лучше всего с полным путем, чтобы сделать пакетный файл независимым от переменных среды PATHEXT и PATH.

...