Руководство по последовательному выполнению batch‑скриптов
Узнайте, как правильно последовательно запускать несколько .BAT файлов с помощью команды call, включая обработку ошибок, логирование и лучшие практики для мастер‑скриптов Windows.
Как выполнить несколько файлов .BAT последовательно в скрипте Windows batch?
Я пытаюсь создать основной batch-файл под названием commit-build.bat, который будет последовательно запускать другие batch-файлы в рамках нашего процесса сборки. Текущее содержимое моего основного скрипта выглядит так:
"msbuild.bat"
"unit-tests.bat"
"deploy.bat"
Однако при запуске выполняется только первый файл (msbuild.bat), а остальные игнорируются. Я проверил, что каждый из этих batch-файлов работает корректно, когда запускается отдельно. Какой правильный синтаксис, чтобы все batch-файлы выполнялись в порядке следования внутри основного скрипта?
Правильный синтаксис для последовательного выполнения нескольких файлов .BAT в пакетном скрипте Windows требует использования команды call перед каждым именем файла .BAT. В вашем текущем подходе выполняется только первый скрипт, потому что пакетные файлы завершаются после выполнения без команды call.
Вот исправленная версия вашего commit-build.bat:
call msbuild.bat
call unit-tests.bat
call deploy.bat
Команда call сообщает процессору пакетов выполнить указанный пакетный файл, а затем вернуться к основному скрипту и продолжить выполнение следующей команды. Без неё процессор пакетов выполнит msbuild.bat и никогда не вернётся, фактически игнорируя оставшиеся команды.
Содержание
- Понимание команды
call - Лучшие практики для мастер‑скриптов
- Обработка ошибок и логирование
- Работа с разными каталогами
- Полный пример мастер‑скрипта
- Частые советы по устранению неполадок
Понимание команды call
Команда call необходима для последовательного выполнения пакетных файлов в скриптах Windows. Когда вы запускаете пакетный файл напрямую (без call), исходный скрипт ожидает завершения вызванного скрипта, но не сохраняет контекст должным образом.
Ключевые различия:
- Без
call: Скрипт выполняется и завершается, не возвращаясь к мастер‑скрипту - С
call: Скрипт выполняется, завершается и управление возвращается к мастер‑скрипту
Базовый синтаксис:
call [drive:][path]filename [batch-parameters]
Примеры:
call msbuild.bat
call "C:\scripts\unit-tests.bat"
call "%~dp0deploy.bat"
Кавычки вокруг имён файлов нужны только тогда, когда путь содержит пробелы.
Лучшие практики для мастер‑скриптов
Создание эффективного мастер‑скрипта включает несколько рекомендаций:
1. Используйте абсолютные или относительные пути
call scripts\msbuild.bat
call ..\tests\unit-tests.bat
call "%~dp0deploy.bat"
2. Добавьте логирование и сообщения о статусе
@echo Starting build process...
call msbuild.bat
if %ERRORLEVEL% neq 0 (
echo Build failed!
exit /b 1
)
echo Running unit tests...
call unit-tests.bat
if %ERRORLEVEL% neq 0 (
echo Unit tests failed!
exit /b 1
)
echo Deploying application...
call deploy.bat
if %ERRORLEVEL% neq 0 (
echo Deployment failed!
exit /b 1
)
echo All operations completed successfully!
3. Установите правильную среду
@echo off
setlocal enabledelayedexpansion
title Build Process
Обработка ошибок и логирование
Надёжные пакетные скрипты должны включать надёжную обработку ошибок и логирование:
Базовая проверка ошибок
@echo off
echo Starting build process...
call msbuild.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: msbuild.bat failed with error code %ERRORLEVEL%
exit /b %ERRORLEVEL%
)
echo msbuild.bat completed successfully.
call unit-tests.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: unit-tests.bat failed with error code %ERRORLEVEL%
exit /b %ERRORLEVEL%
)
echo unit-tests.bat completed successfully.
call deploy.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: deploy.bat failed with error code %ERRORLEVEL%
exit /b %ERRORLEVEL%
)
echo deploy.bat completed successfully.
echo Build process completed successfully!
Расширенное логирование
@echo off
set LOGFILE=build_%DATE:~-4,4%%DATE:~-7,2%%DATE:~-10,2%_%TIME:~0,2%%TIME:~3,2%.log
echo Build started at %DATE% %TIME% > %LOGFILE%
echo. >> %LOGFILE%
call msbuild.bat 2>&1 | tee -a %LOGFILE%
if %ERRORLEVEL% neq 0 (
echo ERROR: msbuild.bat failed! See %LOGFILE% for details.
exit /b %ERRORLEVEL%
)
call unit-tests.bat 2>&1 | tee -a %LOGFILE%
if %ERRORLEVEL% neq 0 (
echo ERROR: unit-tests.bat failed! See %LOGFILE% for details.
exit /b %ERRORLEVEL%
)
call deploy.bat 2>&1 | tee -a %LOGFILE%
if %ERRORLEVEL% neq 0 (
echo ERROR: deploy.bat failed! See %LOGFILE% for details.
exit /b %ERRORLEVEL%
)
echo All operations completed successfully! >> %LOGFILE%
echo Build completed successfully! See %LOGFILE% for details.
Работа с разными каталогами
Если ваши пакетные файлы находятся в разных каталогах, нужно правильно обрабатывать пути:
Метод текущего каталога
@echo off
setlocal
call msbuild.bat
cd /d "%~dp0"
call scripts\unit-tests.bat
cd /d "%~dp0"
call deploy\deploy.bat
echo All scripts executed successfully.
Метод pushd/popd
@echo off
setlocal
call msbuild.bat
pushd "%~dp0scripts"
call unit-tests.bat
popd
pushd "%~dp0deploy"
call deploy.bat
popd
echo All scripts executed successfully.
Полный пример мастер‑скрипта
Ниже приведён полный пример commit-build.bat со всеми лучшими практиками:
@echo off
setlocal enabledelayedexpansion
title Build Process
:: Установить файл логов с временной меткой
set LOGFILE=build_%DATE:~-4,4%%DATE:~-7,2%%DATE:~-10,2%_%TIME:~0,2%%TIME:~3,2%.log
set LOGDIR=%~dp0logs
:: Создать каталог логов, если он не существует
if not exist "%LOGDIR%" mkdir "%LOGDIR%"
:: Инициализировать лог
echo Build Process Started: %DATE% %TIME% > "%LOGDIR%\%LOGFILE%"
echo Build Master Script: %~nx0 >> "%LOGDIR%\%LOGFILE%"
echo. >> "%LOGDIR%\%LOGFILE%"
:: Выполнить скрипт сборки
echo Executing msbuild.bat...
call msbuild.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: msbuild.bat failed with error code %ERRORLEVEL%
echo ERROR: msbuild.bat failed with error code %ERRORLEVEL% >> "%LOGDIR%\%LOGFILE%"
exit /b %ERRORLEVEL%
)
echo msbuild.bat completed successfully. >> "%LOGDIR%\%LOGFILE%"
:: Выполнить unit‑тесты
echo Executing unit-tests.bat...
call unit-tests.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: unit-tests.bat failed with error code %ERRORLEVEL%
echo ERROR: unit-tests.bat failed with error code %ERRORLEVEL% >> "%LOGDIR%\%LOGFILE%"
exit /b %ERRORLEVEL%
)
echo unit-tests.bat completed successfully. >> "%LOGDIR%\%LOGFILE%"
:: Выполнить деплой
echo Executing deploy.bat...
call deploy.bat
if %ERRORLEVEL% neq 0 (
echo ERROR: deploy.bat failed with error code %ERRORLEVEL%
echo ERROR: deploy.bat failed with error code %ERRORLEVEL% >> "%LOGDIR%\%LOGFILE%"
exit /b %ERRORLEVEL%
)
echo deploy.bat completed successfully. >> "%LOGDIR%\%LOGFILE%"
:: Завершить процесс сборки
echo. >> "%LOGDIR%\%LOGFILE%"
echo Build Process Completed: %DATE% %TIME% >> "%LOGDIR%\%LOGFILE%"
echo Build process completed successfully!
echo Log file created at: "%LOGDIR%\%LOGFILE%"
endlocal
Частые советы по устранению неполадок
1. Ошибки «Файл не найден»
Если вы видите ошибки «file not found»:
- Проверьте, что пути к файлам корректны
- Используйте
%~dp0для ссылки на каталог скрипта - Убедитесь, что в названиях файлов нет опечаток
2. Скрипт останавливается
Если скрипты перестают выполняться:
- Убедитесь, что перед каждым пакетным файлом используется
call - Проверьте, не содержат ли скрипты команды
exitилиexit /bбез надлежащей обработки ошибок - Убедитесь, что в предыдущих скриптах нет бесконечных циклов
3. Проблемы с рабочим каталогом
Если скрипты не могут найти файлы:
- Используйте
cd /dдля смены каталогов между скриптами - Используйте абсолютные пути для всех операций с файлами
- Рассмотрите возможность использования
pushdиpopdдля управления каталогами
4. Переменные окружения
Если переменные окружения не работают:
- Правильно используйте
setlocalиendlocal - При сложной работе с переменными рассмотрите
setlocal enabledelayedexpansion
5. Советы по отладке
Добавьте информацию об отладке:
@echo on :: Показать все выполняемые команды
echo Current directory: %CD%
echo Error level: %ERRORLEVEL%
Помните, что надёжная обработка ошибок и логирование критически важны для продакшн‑скриптов, так как они помогают быстро выявлять и устранять проблемы при автоматизированных сборках.