¿Cómo puedo hacer que un archivo por lotes termine al encontrar un error?
Tengo un archivo por lotes que está llamando al mismo ejecutable una y otra vez con diferentes parámetros. ¿Cómo puedo hacer 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.
10 answers
Compruebe el errorlevel
en una instrucción if
, y luego exit /b
(salga solo del archivo b atch, no de todo el cmd.proceso exe) para valores distintos de 0.
same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%
Si desea que el valor del nivel de error se propague fuera de su archivo por lotes
if %errorlevel% neq 0 exit /b %errorlevel%
Pero si esto está dentro de un for
se pone 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!
)
Edit: Tienes que comprobar el error después de cada comando. No hay un 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 errorlevel negativo en ninguno de mis lotes de hacking en XP o Vista.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:14
Agregue || goto :label
a cada línea, y luego defina un :label
.
Por ejemplo, cree esto .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%
Ver también pregunta sobre cómo salir de la subrutina del archivo por lotes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-20 10:18:19
El más corto:
command || exit /b
Si lo necesita, puede establecer el código de salida:
command || exit /b 666
Y también puedes registrar:
command || echo ERROR && exit /b
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-20 15:26:00
Una actualización menor, debe cambiar las comprobaciones de "if errorlevel 1" a lo siguiente...
IF %ERRORLEVEL% NEQ 0
Esto se debe a que en XP puede obtener números negativos como errores. 0 = no hay problemas, cualquier otra cosa es un problema.
Y tenga en cuenta la forma en que DOS maneja las pruebas "IF ERRORLEVEL". Devolverá true si el número que está buscando es ese número o mayor, por lo que si está buscando números de error específicos, debe comenzar con 255 y trabajar hacia abajo.
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 utilizado este tipo de cosas en el pasado para una plataforma múltiple integración continua script.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 14:55:15
Prefiero la forma de comando OR, ya que los encuentro más legibles (como
opuesto a tener un si después de cada comando). Sin embargo, la manera ingenua de
hacer esto, command || exit /b %ERRORLEVEL%
es incorrecto.
Esto se debe a que batch expande las variables cuando se lee una línea por primera vez, en lugar de
que cuando se están utilizando. Esto significa que si el command
en la línea
arriba 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%
era al comienzo de la
alinear. Obviamente, esto es indeseable en nuestro script, por lo que tenemos que habilitar
expansión retardada, así:
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, salga con el mismo código de salida que el comando fallido.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-17 14:20:18
No siempre podemos depender de ERRORLEVEL, porque muchas veces los programas externos o los scripts por lotes no devuelven los códigos de salida.
En ese caso podemos usar comprobaciones genéricas para fallos como este:
IF EXIST %outfile% (DEL /F %outfile%)
CALL some_script.bat -o %outfile%
IF NOT EXIST %outfile% (ECHO ERROR & EXIT /b)
Y si el programa da salida a algo para consolar, podemos comprobarlo también.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-26 06:11:44
No importa cómo lo intente, el nivel de error siempre permanece 0 incluso cuando msbuild falló. Así que construí mi solución:
Compilar proyecto y guardar registro para compilar.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%
Obtiene el último carácter, que indica cuántas líneas contiene la cadena de búsqueda
set result=%var:~-1%
echo "%result%"
Si string no se encuentra, entonces error > 0, build failed
if "%result%"=="0" ( echo "build failed" )
Esa solución fue inspirada por el post de Mechaflash en Cómo establecer la salida de comandos como una variable en un archivo por lotes
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-05 15:13:22
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-25 02:43:16
@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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-05 23:50:41