Как запустить несколько файлов.BAT в файле.BAT
Я пытаюсь получить commit-build.bat
выполнить другие файлы.BAT как часть нашего процесса сборки.
Содержание commit-build.bat
:
"msbuild.bat"
"unit-tests.bat"
"deploy.bat"
Это кажется достаточно простым, но commit-build.bat
выполняет только первый элемент в списке (msbuild.bat
).
Я запустил каждый из файлов отдельно без проблем.
19 ответов
Использование:
call msbuild.bat
call unit-tests.bat
call deploy.bat
Если CALL не используется, текущий пакетный файл останавливается, и запускаемый вызываемый пакетный файл начинает выполняться. Это своеобразное поведение, восходящее к ранним дням MS-DOS.
Все остальные ответы верны: используйте звонок. Например:
call "msbuild.bat"
история
В древних версиях DOS было невозможно рекурсивно выполнять командные файлы. Затем была введена команда call, которая вызвала другую командную оболочку cmd для выполнения командного файла и вернула выполнение обратно в вызывающую командную оболочку по окончании.
Очевидно, что в более поздних версиях больше нет необходимости в других оболочках cmd.
В первые дни многие пакетные файлы зависели от того, что вызов пакетного файла не вернется к вызывающему пакетному файлу. Изменение этого поведения без дополнительного синтаксиса нарушило бы многие системы, такие как системы пакетного меню (используя пакетные файлы для структур меню).
Как и во многих случаях с Microsoft, причиной такого поведения является обратная совместимость.
подсказки
Если в ваших пакетных файлах есть пробелы в именах, используйте кавычки вокруг имени:
call "unit tests.bat"
Кстати: если у вас нет всех имен пакетных файлов, вы также можете использовать для этого (это не гарантирует правильный порядок вызовов пакетных файлов; он следует порядку файловой системы):
FOR %x IN (*.bat) DO call "%x"
Вы также можете реагировать на уровни ошибок после вызова. Использование:
exit /B 1 # Or any other integer value in 0..255
вернуть уровень ошибки. 0 обозначает правильное выполнение. В вызывающем пакетном файле вы можете реагировать, используя
if errorlevel neq 0 <batch command>
использование if errorlevel 1
Если у вас Windows старше NT4/2000/XP, чтобы перехватить все уровни ошибок 1 и выше.
Для управления потоком командного файла есть goto:-(
if errorlevel 2 goto label2
if errorlevel 1 goto label1
...
:label1
...
:label2
...
Как отмечали другие: взгляните на системы сборки для замены командных файлов.
Если мы хотим открыть несколько командных строк, то мы могли бы использовать
start cmd /k
/k
: обязательно, что выполнит.
Запуск многих командных приглашений можно выполнить, как показано ниже.
start cmd /k Call rc_hub.bat 4444
start cmd /k Call rc_grid1.bat 5555
start cmd /k Call rc_grid1.bat 6666
start cmd /k Call rc_grid1.bat 5570.
Пытаться:
call msbuild.bat
call unit-tests.bat
call deploy.bat
используя "&"
Как вы заметили, запуск биты напрямую без
CALL
,START
,
CMD /C
вызывает ввод и выполнение первого файла, а затем процесс останавливается по завершении первого файла. Хотя вы все еще можете использовать
&
что будет таким же, как при использовании
command1 & command2
прямо в консоли:
(
first.bat
)&(
second.bat
)& (
third.bat
)&(
echo other commands
)
С точки зрения машинных ресурсов это будет наиболее эффективным способом, хотя в последнем блоке вы хотите иметь возможность использовать командную строку.
GOTO
,SHIFT
,SETLOCAL
.. и его возможности будут почти такими же, как при выполнении команд в командной строке. И вы не сможете выполнить другую команду после последней закрывающей скобки
Использование CALL
call first.bat
call second.bat
call third.bat
В большинстве случаев это будет лучший подход - он не создает отдельный процесс, но ведет себя почти так же, как вызов
:label
как подпрограмма. В терминологии MS он создает новый контекст командного файла и передает управление оператору после указанной метки. При первом обнаружении конца командного файла (то есть после перехода к метке) управление возвращается оператору после заявление о вызове ".
Вы можете использовать переменные, установленные в вызываемых файлах (если они не установлены в
SETLOCAL
block), вы можете напрямую обращаться к меткам в вызываемом файле.
CMD /C
, Трубы,FOR /F
разное
native
вариант - использовать
CMD /C
(переключатель /C заставит вызываемую консоль выйти и вернуть управление) Что-то, что cmd.exe делает непрозрачным способом с использованием
FOR /F
против файла bat или когда используются трубы. Это порождает дочерний процесс, в котором будет вся среда вызывающей летучей мыши. Менее эффективен с точки зрения ресурсов, но поскольку процесс отдельный, при анализе происходит сбой или вызывается
EXIT
команда не остановит вызывающий.bat
@echo off
CMD /c first.bat
CMD /C second.bat
::not so different than the above lines.
:: MORE,FINDSTR,FIND command will be able to read the piped data
:: passed from the left side
break|third.bat
НАЧАЛО
Обеспечивает большую гибкость, так как возможность запускать сценарии в отдельном окне, не ждать их завершения, устанавливать заголовок и так далее. По умолчанию запускается
.bat
и
.cmd
сценарии с
CMD /K
Это означает, что порожденные скрипты не будут закрыты автоматически. Снова передает всю среду запущенным скриптам и потребляет больше ресурсов, чем
cmd /c
:
:: will be executed in the same console window and will wait to finish
start "" /b /w cmd /c first.bat
::will start in a separate console window and WONT wait to be finished
:: the second console window wont close automatically so second.bat might need explicit exit command
start "" second.bat
::Will start it in a separate window ,but will wait to finish
:: closing the second window will cause Y/N prompt
:: in the original window
start "" /w third.cmd
::will start it in the same console window
:: but wont wait to finish. May lead to a little bit confusing output
start "" /b cmd /c fourth.bat
WMIC
В отличие от других методов, теперь в примерах будут использоваться внешние служебные программы CMD.exe (которые по-прежнему доступны в Windows по умолчанию). Утилита WMIC создаст полностью отдельный процесс, поэтому вы не сможете напрямую ждать его завершения. Хотя лучшая особенность WMIC заключается в том, что он возвращает идентификатор порожденного процесса:
:: will create a separate process with cmd.exe /c
WMIC process call create "%cd%\first.bat","%cd%"
::you can get the PID and monitoring it with other tools
for /f "tokens=2 delims=;= " %%# in ('WMIC process call create "%cd%\second.bat"^,"%cd%" ^|find "ProcessId"') do (
set "PID=%%#"
)
echo %PID%
Вы также можете использовать его для запуска процесса на удаленной машине с другим пользователем и так далее.
SCHTASKS
Использование SCHTASKS предоставляет некоторые функции, такие как (очевидное) планирование, запуск от имени другого пользователя (даже системного пользователя), удаленный запуск машины и так далее. Снова запускает его в совершенно отдельной среде (то есть в собственных переменных) и даже в скрытом процессе, XML-файле с параметрами команды и т. Д.:
SCHTASKS /create /tn BatRunner /tr "%cd%\first.bat" /sc ONCE /sd 01/01/1910 /st 00:00
SCHTASKS /Run /TN BatRunner
SCHTASKS /Delete /TN BatRunner /F
Здесь PID также можно получить из журнала событий.
ScriptRunner
Предлагает некоторый тайм-аут между запускаемыми скриптами. Основные возможности транзакции (например, откат при ошибке) и параметры могут быть помещены в отдельный файл XML.
::if the script is not finished after 15 seconds (i.e. ends with pause) it will be killed
ScriptRunner.exe -appvscript %cd%\first.bat -appvscriptrunnerparameters -wait -timeout=15
::will wait or the first called script before to start the second
:: if any of the scripts exit with errorcode different than 0 will try
:: try to restore the system in the original state
ScriptRunner.exe -appvscript second.cmd arg1 arg2 -appvscriptrunnerparameters -wait -rollbackonerror -appvscript third.bat -appvscriptrunnerparameters -wait -timeout=30 -rollbackonerror
Если у нас есть два пакетных сценария, aaa.bat и bbb.bat, и вызовите, как показано ниже
call aaa.bat
call bbb.bat
При выполнении сценария он сначала вызовет aaa.bat, дождется завершения потока aaa.bat и вызовет bbb.bat.
Но если вы не хотите ждать, пока aaa.bat завершит вызов bbb.bat, попробуйте использовать команду START:
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/AFFINITY <hex affinity>] [/WAIT] [/B] [command/program]
[parameters]
Экзамен:
start /b aaa.bat
start /b bbb.bat
Вы вызываете несколько пакетов, чтобы скомпилировать программу. Я считаю само собой разумеющимся, что если возникает ошибка:
1) Программа в пакете выйдет с уровнем ошибки;
2) Вы хотите знать об этом.
for %%b in ("msbuild.bat" "unit-tests.bat" "deploy.bat") do call %%b|| exit /b 1
'||' проверяет уровень ошибки выше 0. Таким образом, все пакеты вызываются по порядку, но останавливаются при любой ошибке, оставляя экран, в котором вы видите любое сообщение об ошибке.
Чтобы позвонить .bat
файл в .bat
файл, использовать
call foo.bat
(Да, это глупо, было бы больше смысла, если бы вы могли позвонить с foo.bat
, как вы могли бы из командной строки, но правильный способ заключается в использовании call
.)
Параллельный запуск нескольких пакетных файлов
start "systemLogCollector" /min cmd /k call systemLogCollector.bat
start "uiLogCollector" /min cmd /k call uiLogCollector.bat
start "appLogCollector" /min cmd /k call appLogCollector.bat
Здесь три командных файла запускаются в отдельных командных окнах в свернутом состоянии. Если вы не хотите, чтобы они сворачивались, удалите/min
. Кроме того, если вам не нужно управлять ими позже, вы можете избавиться от заголовков. Итак, простая команда будет -start cmd /k call systemLogCollector.bat
Если вы хотите прекратить их -
taskkill /FI "WindowTitle eq appLogCollector*" /T /F
taskkill /FI "WindowTitle eq uiLogCollector*" /T /F
taskkill /FI "WindowTitle eq systemLogCollector*" /T /F
Start msbuild.bat
Start unit-tests.bat
Start deploy.bat
Если это не сработает, замените start
с call
или попробуйте это:
Start msbuild.bat
Goto :1
:1
Start unit-tests.bat
Goto :2
:2
Start deploy.bat
Глядя на ваши имена файлов, вы рассматривали возможность использования инструмента сборки, такого как NAnt или Ant (версия Java). Вы получите гораздо больше контроля, чем с файлами Bat.
Если вы хотите открыть много командных файлов одновременно, вы можете использовать команду call. Однако команда call закрывает текущий bat-файл и переходит к другому. Если вы хотите открыть много сразу, вы можете попробовать это:
@echo off
start cmd "call ex1.bat&ex2.bat&ex3.bat"
И так далее или повторить старт cmd
"call
... "для любого количества файлов. Это работает для Windows 7, но я не уверен насчет других систем.
Ваш сценарий должен быть:
start "msbuild.bat"
start "unit-tests.bat"
start "deploy.bat"
При правильном цитировании (иногда это бывает сложно):
start "" /D "C:\Program Files\ProgramToLaunch" "cmd.exe" "/c call ""C:\Program Files\ProgramToLaunch\programname.bat"""
1-й аргумент - заголовок (в данном случае пуст)
2nd arg - / D указывает начальный каталог, может быть опущен, если требуется текущий рабочий каталог (например, "% ~ dp0")
3-й аргумент - команда для запуска, "cmd.exe"
4-й аргумент - аргументы команды, с двойными кавычками для аргументов внутри нее (это то, как вы избегаете кавычек внутри кавычек в пакете)
Просто используйте call
команда! Вот пример:
call msbuild.bat
call unit-tests.bat
call deploy.bat
Я знаю, что немного опаздываю на вечеринку, но есть другой выход. То есть этот метод должен дождаться завершения первого, второго и т. Д.
start "" /wait cmd.exe /c msbuild.bat
start "" /wait cmd.exe /c unit-tests.bat
start "" /wait cmd.exe /c deploy.bat
Единственная проблема, которая может возникнуть при использовании этого метода, заключается в том, что при создании новых экземпляров cmd.exe проверка уровня ошибок сохраняется в каждом экземпляре cmd.exe.
Или..
start "" /wait call msbuild.bat
start "" /wait call unit-tests.bat
start "" /wait call deploy.bat
Надеюсь это поможет.
Запуск нескольких сценариев в одном у меня была та же проблема. Я продолжал заставлять его умирать на первом, не понимая, что это выход на первом сценарии.
:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT
:: ScriptA.bat
Do Foo
EXIT
::ScriptB.bat
Do bar
EXIT
Я удалил все 11 из моих строк сценариев EXIT и попытался снова, и все 11 работали по порядку в одном и том же командном окне.
:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT
::ScriptA.bat
Do Foo
::ScriptB.bat
Do bar
Вот мой путь =
cmd /c ""Path_Bat_Here.bat" %ARG%"
:: Or =
Call *.bat
Помощь = cmd /?