Как заставить пакетный файл завершиться при возникновении ошибки?
У меня есть пакетный файл, который вызывает один и тот же исполняемый файл снова и снова с разными параметрами. Как заставить его немедленно завершиться, если один из вызовов возвращает код ошибки любого уровня?
в принципе, я хочу, что эквивалентно .
10 ответов:
Регистрация
errorlevelнаifзаявление, а потомexit /b(выход bтолько файл atch, а не весь cmd.exe process) для значений, отличных от 0.same-executable-over-and-over.exe /with different "parameters" if %errorlevel% neq 0 exit /b %errorlevel%если вы хотите, чтобы значение errorlevel распространялось за пределы вашего пакетного файла
if %errorlevel% neq 0 exit /b %errorlevel%но если это внутри
forэто становится немного сложнее. Вам понадобится что-то вроде:setlocal enabledelayedexpansion for %%f in (C:\Windows\*) do ( same-executable-over-and-over.exe /with different "parameters" if !errorlevel! neq 0 exit /b !errorlevel! )Edit: вы должны проверить ошибку после каждой команды. В пакете cmd.exe/command.com нет глобального типа конструкции "on error goto". Я также обновил свой код на CodeMonkey, хотя я никогда не сталкивался с отрицательным уровнем ошибок в любом из моих пакетных взломов на XP или Vista.
добавить
|| goto :labelк каждой строке, а затем определить:label.например, создайте это .файл cmd:
@echo off echo Starting very complicated batch file... ping -invalid-arg || goto :error echo OH noes, this shouldn't have succeeded. goto :EOF :error echo Failed with error #%errorlevel%. exit /b %errorlevel%
минимальные:
command || exit /bЕсли вам нужно, вы можете установить код на выходе:
command || exit /b 666и вы также можете войти:
command || echo ERROR && exit /b
одно незначительное обновление, вы должны изменить проверки для "Если errorlevel 1" на следующее...
IF %ERRORLEVEL% NEQ 0Это потому, что на XP вы можете получить отрицательные числа в качестве ошибок. 0 = Нет проблем, все остальное-это проблема.
и имейте в виду, как DOS обрабатывает тесты "IF ERRORLEVEL". Он вернет true, если число, которое вы проверяете, является этим числом или выше, поэтому, если вы ищете конкретные номера ошибок, вам нужно начать с 255 и работать вниз.
здесь полиглот программа для BASH и Windows CMD, который выполняет ряд команд и завершает работу, если какой-либо из них не удается:
#!/bin/bash 2> nul :; set -o errexit :; function goto() { return $?; } command 1 || goto :error command 2 || goto :error command 3 || goto :error :error :; exit 0 exit /b 0 :error exit /b %errorlevel%я использовал этот тип вещи в прошлом для нескольких платформ непрерывная интеграция сценарий.
Я предпочитаю или форму команды, так как я нахожу их наиболее читаемыми (как против того, чтобы иметь if после каждой команды). Однако, наивный путь делая это,
command || exit /b %ERRORLEVEL%и неправильно.это потому, что пакет расширяет переменные при первом чтении строки, а не чем когда они используются. Это означает, что если
commandв строке выше сбой, пакетный файл завершает работу правильно, но он завершается с кодом возврата 0, потому что значение%ERRORLEVEL%был в начало линия. Очевидно, что это нежелательно в нашем скрипте, поэтому мы должны включить отложенная экспансия, например:SETLOCAL EnableDelayedExpansion command-1 || exit /b !ERRORLEVEL! command-2 || exit /b !ERRORLEVEL! command-3 || exit /b !ERRORLEVEL! command-4 || exit /b !ERRORLEVEL!этот фрагмент будет выполнять команды 1-4, и если какой-либо из них не удастся, он будет выход с тем же кодом выхода, так как не выполнила.
мы не всегда можем зависеть от ERRORLEVEL, потому что много раз внешние программы или пакетные сценарии не возвращают коды выхода.
в этом случае мы можем использовать общие проверки для сбоев, как это:
IF EXIST %outfile% (DEL /F %outfile%) CALL some_script.bat -o %outfile% IF NOT EXIST %outfile% (ECHO ERROR & EXIT /b)и если программа выводит что-то на консоль, мы также можем это проверить.
some_program.exe 2>&1 | FIND "error message here" && (ECHO ERROR & EXIT /b) some_program.exe 2>&1 | FIND "Done processing." || (ECHO ERROR & EXIT /b)
независимо от того, как я пытался, errorlevel всегда остается 0, даже если msbuild не удалось. Поэтому я построил свой обходной путь:
построить проект и сохранить журнал для сборки.журнал
SET Build_Opt=/flp:summary;logfile=Build.log;append=true msbuild "myproj.csproj" /t:rebuild /p:Configuration=release /fl %Build_Opt%поиск строки "0 Error" в журнале сборки, установите результат в var
FOR /F "tokens=* USEBACKQ" %%F IN (`find /c /i "0 Error" Build.log`) DO ( SET var=%%F ) echo %var%получить последний символ, который указывает, сколько строк содержит строку поиска
set result=%var:~-1% echo "%result%"если строка не найдена, то error > 0, build failed
if "%result%"=="0" ( echo "build failed" )это решение было вдохновленный сообщением Mechaflash в как установить команды, выводимые в виде переменной в пакетном файле
просто использовать
ERRORLEVELдля достижения желаемого результата. Есть две переменные вERRORLEVELкоманда, которая определит, если процесс не удалось или успешно, эти переменныеERRORLEVEL 0иERRORLEVEL 1(1 для fail, 0 для pass). Вот пример того, как это будет использоваться в пакетном файле:echo off cls ping localhost errorlevel 0 goto :good errorlevel 1 goto :bad :good cls echo Good! echo[ pause exit :bad cls echo Bad! echo[ pause exitвот ссылка с дополнительной информацией, если вам это нужно: Errorlevels
@echo off set startbuild=%TIME% C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe c:\link.xml /flp1:logfile=c:\link\errors.log;errorsonly /flp2:logfile=c:\link\warnings.log;warningsonly || goto :error copy c:\app_offline.htm "\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm" del \lawpccnweb01\d$\websites\OperationsLinkWeb\bin\ /Q echo Start Copy: %TIME% set copystart=%TIME% xcopy C:\link\_PublishedWebsites\OperationsLink \lawpccnweb01\d$\websites\OperationsLinkWeb\ /s /y /d del \lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm echo Started Build: %startbuild% echo Started Copy: %copystart% echo Finished Copy: %TIME% c:\link\warnings.log :error c:\link\errors.log
Comments