make how example create commands batch batch-file

batch-file - example - how to use batch file



¿Cómo hago que un archivo por lotes termine al encontrar un error? (10)

Añadir || goto :label || goto :label en cada línea y luego definir una :label

Por ejemplo, cree este archivo .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%

Consulte también la pregunta sobre cómo salir de la subrutina de archivo por lotes .

Tengo un archivo por lotes que llama al mismo ejecutable una y otra vez con diferentes parámetros. ¿Cómo hago que termine inmediatamente si una de las llamadas devuelve un código de error de cualquier nivel?

Básicamente, quiero el equivalente de ContinueOnError=false de MSBuild.


Aquí hay un programa políglota para BASH y Windows CMD que ejecuta una serie de comandos y se cierra si alguno de ellos falla:

#!/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%

He usado este tipo de cosas en el pasado para una secuencia de comandos de integración continua de múltiples plataformas.


El más corto:

command || exit /b

Si lo necesita, puede configurar el código de salida:

command || exit /b 666

Y también puedes iniciar sesión:

command || echo ERROR && exit /b


No importa cómo lo intenté, el errorlevel siempre permanece 0 incluso cuando msbuild falló. Así que construí mi solución:

Genere el proyecto y guarde el registro en Build.log

SET Build_Opt=/flp:summary;logfile=Build.log;append=true msbuild "myproj.csproj" /t:rebuild /p:Configuration=release /fl %Build_Opt%

busque la cadena "0 Error" en el registro de compilación, establezca el resultado en var

FOR /F "tokens=* USEBACKQ" %%F IN (`find /c /i "0 Error" Build.log`) DO ( SET var=%%F ) echo %var%

obtener el último carácter, que indica cuántas líneas contiene la cadena de búsqueda

set result=%var:~-1% echo "%result%"

si no se encuentra la cadena, entonces error> 0, la compilación falló

if "%result%"=="0" ( echo "build failed" )

Esa solución se inspiró en la publicación de Mechaflash en Cómo configurar la salida de comandos como una variable en un archivo por lotes

y https://ss64.com/nt/syntax-substring.html


No siempre podemos depender de ERRORLEVEL, porque muchas veces los programas externos o las secuencias de comandos por lotes no devuelven códigos de salida.

En ese caso podemos usar cheques genéricos para fallas como esta:

IF EXIST %outfile% (DEL /F %outfile%) CALL some_script.bat -o %outfile% IF NOT EXIST %outfile% (ECHO ERROR & EXIT /b)

Y si el programa genera algo para la consola, también podemos verificarlo.

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)


Prefiero la forma de comando OR, ya que los considero los más legibles (en lugar de tener un if después de cada comando). Sin embargo, la forma ingenua de hacer esto, command || exit /b %ERRORLEVEL% command || exit /b %ERRORLEVEL% es incorrecto .

Esto se debe a que el lote expande las variables cuando se lee una línea por primera vez, en lugar de cuando se están utilizando. Esto significa que si el command en la línea anterior falla, el archivo por lotes sale correctamente, pero sale con el código de retorno 0, porque eso es lo que el valor de %ERRORLEVEL% estaba al comienzo de la línea. Obviamente, esto es indeseable en nuestro script, por lo que tenemos que habilitar la expansión demorada , de esta manera:

SETLOCAL EnableDelayedExpansion command-1 || exit /b !ERRORLEVEL! command-2 || exit /b !ERRORLEVEL! command-3 || exit /b !ERRORLEVEL! command-4 || exit /b !ERRORLEVEL!

Este fragmento ejecutará los comandos 1-4, y si alguno de ellos falla, saldrá con el mismo código de salida que el comando fallido.


Simplemente use ERRORLEVEL para lograr el resultado que desea. Hay dos variables en el comando ERRORLEVEL que determinarían si un proceso falló o tuvo éxito, estas variables son ERRORLEVEL 0 y ERRORLEVEL 1 (1 para fail, 0 para pass). Aquí hay un ejemplo de cómo se usaría esto en un archivo por lotes:

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

Aquí hay un enlace con más información si lo necesita: Errorlevels


Una actualización menor, debe cambiar las comprobaciones de "if errorlevel 1" a la siguiente ...

IF %ERRORLEVEL% NEQ 0

Esto es porque en XP puedes obtener números negativos como errores. 0 = sin problemas, cualquier otra cosa es un problema.

Y tenga en cuenta la forma en que DOS maneja las pruebas "IF ERRORLEVEL". Devolverá verdadero si el número que está verificando es ese número o superior, por lo que si está buscando números de error específicos, debe comenzar con 255 y trabajar hacia abajo.


Verifique el nivel de errorlevel en una instrucción if , y luego exit /b (solo salga del archivo b atch, no todo el proceso de cmd.exe) para valores que no sean 0.

same-executable-over-and-over.exe /with different "parameters" if %errorlevel% neq 0 exit /b %errorlevel%

Si desea que el valor de errorlevel se propague fuera de su archivo por lotes

if %errorlevel% neq 0 exit /b %errorlevel%

Pero si esto está dentro, se vuelve un poco complicado. Necesitarás algo más como:

setlocal enabledelayedexpansion for %%f in (C:/Windows/*) do ( same-executable-over-and-over.exe /with different "parameters" if !errorlevel! neq 0 exit /b !errorlevel! )

Editar: Tienes que verificar el error después de cada comando. No hay ningún tipo de construcción global "on error goto" en cmd.exe / command.com batch. También he actualizado mi código por CodeMonkey , aunque nunca he encontrado un nivel de error negativo en ninguno de mis ataques por lotes en XP o Vista.


@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