¿Conseguir que ROBOCOPY devuelva un código de salida "correcto"?

121

¿Es posible pedirle a ROBOCOPY que salga con un código de salida que indica éxito o fracaso?

Estoy usando ROBOCOPY como parte de mis configuraciones de construcción de TeamCity, y tener que agregar un paso para silenciar el código de salida de ROBOCOPY me parece una tontería.

Básicamente, he agregado esto:

EXIT /B 0

al script que se está ejecutando.

Sin embargo, esto, por supuesto, oculta cualquier problema real que ROBOCOPY devolvería.

Básicamente, me gustaría tener códigos de salida de 0 para SUCCESS y no-zero para FAILURE en lugar de la máscara de bits que ROBOCOPY devuelve ahora.

O, si no puedo tener eso, ¿hay una secuencia simple de comandos por lotes que traduciría la máscara de bits de ROBOCOPY a un valor similar?

Lasse Vågsæther Karlsen
fuente
2
También debe tenerse en cuenta que los primeros 8 códigos de salida (0-7) aparentemente no son estados de error: stackoverflow.com/questions/16533843/psake-and-robocopy-failing
longda

Respuestas:

47

Según aquí , Robocopy tiene los siguientes bits de código de salida que forman el código de salida:

0 × 10 Error grave. Robocopy no copió ningún archivo. Esto es un error de uso o un error debido a privilegios de acceso insuficientes en los directorios de origen o destino.

0 × 08 Algunos archivos o directorios no se pudieron copiar (se produjeron errores de copia y se excedió el límite de reintentos). Verifique estos errores más a fondo.

0 × 04 Se detectaron algunos archivos o directorios que no coinciden. Examine el registro de salida. La limpieza es probablemente necesaria.

0 × 02 Se detectaron algunos archivos o directorios adicionales. Examine el registro de salida. Se puede necesitar algo de limpieza.

0 × 01 Uno o más archivos se copiaron correctamente (es decir, han llegado nuevos archivos).

0 × 00 No se produjeron errores y no se realizó ninguna copia. Los árboles de directorio de origen y destino están completamente sincronizados.

Simplemente agregue declaraciones if / else que EXIT /B 0cuando el valor de retorno es 1 o tal vez 0, y de lo EXIT /B 1contrario. Incluso si los archivos pudieran haber sido copiados, hay algo mal que necesitaría intervención manual.

Daniel Beck
fuente
108

TechNet sugiere esta línea para convertir el código de salida en un código de salida más tradicional:

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LEQ 1 exit 0

O esto para ignorar el código de salida por completo (es decir, no me importa si falló o tuvo éxito):

(robocopy c:\dirA c:\dirB *.*) ^& exit 0

Sin embargo, los dos comandos anteriores terminarán un script después de que se haya ejecutado la robocopy. Este es un problema especialmente para las compilaciones de CI. Si desea utilizar robocopy en este escenario, debe configurar el código de error manualmente para los códigos de salida irrelevantes. A continuación, todos los códigos de error inferiores a 8 se reescribirán sin ningún error, y el script continuará si es posible.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Richard Dingwall
fuente
8
Agradable. Necesita corchetes alrededor del comando robocopy, pero me salvó usando un script de contenedor.
TheCodeKing
No pude hacer que esta línea funcione como un paso de compilación de la Línea de Comando en TeamCity. Tuve que moverlo a una línea separada. También agregué el argumento / B al comando de salida, aunque no creo que fuera necesario.
MikeWyatt
Para la implementación de Teamcity (y no solo Teamcity) es útil escribir: IF %ERRORLEVEL% LEQ 3 set errorlevel=0y en la siguiente línea: if %errorlevel% neq 0 exit /b %errorlevel%(si el archivo por lotes consta de varias operaciones, no solo robocopy), porque los códigos OK son menores que 3. ss64.com/nt/robocopy -exit.html
DaoCacao
66
En TeamCity, debe escapar ERRORLEVELcon el doble %%, así: %% ERRORLEVEL %%. De lo contrario, lo considera un parámetro de compilación de TeamCity.
Yan Sklyarenko
2
¿Qué hace el ^&? ss64 dice escapes pero me parece que no se debe escapar?
mlhDev
19

Ejecutarlo desde Jenkins necesita ambos ( )y /B. Si desea ignorar el nivel de error 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Filippo Vitale
fuente
2
LSS 8 podría ser aún mejor :)
Ivan
13

Desde esta página puede agregar una sección a su archivo por lotes que utiliza la lista de códigos de error para generar los errores y ejecutar diferentes secciones de código:

if %ERRORLEVEL% EQU 16 echo ***FATAL ERROR*** & goto end
if %ERRORLEVEL% EQU 15 echo OKCOPY + FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 14 echo FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 13 echo OKCOPY + FAIL + MISMATCHES & goto end
if %ERRORLEVEL% EQU 12 echo FAIL + MISMATCHES& goto end
if %ERRORLEVEL% EQU 11 echo OKCOPY + FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 10 echo FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 9 echo OKCOPY + FAIL & goto end
if %ERRORLEVEL% EQU 8 echo FAIL & goto end
if %ERRORLEVEL% EQU 7 echo OKCOPY + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 6 echo MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 5 echo OKCOPY + MISMATCHES & goto end
if %ERRORLEVEL% EQU 4 echo MISMATCHES & goto end
if %ERRORLEVEL% EQU 3 echo OKCOPY + XTRA & goto end
if %ERRORLEVEL% EQU 2 echo XTRA & goto end
if %ERRORLEVEL% EQU 1 echo OKCOPY & goto end
if %ERRORLEVEL% EQU 0 echo No Change & goto end


:END
REM END OF BATCH FILE
Mokubai
fuente
8

Yo uso esto:

robocopy .....
call :REPORT_ERRORLEVEL
goto :EOF

:REPORT_ERRORLEVEL
echo.
if ERRORLEVEL 16 echo ***FATAL ERROR*** & goto :EOF
if ERRORLEVEL 8 echo **FAILED COPIES** & goto :EOF
if ERRORLEVEL 4 echo *MISMATCHES* & goto :EOF
if ERRORLEVEL 2 echo EXTRA FILES & goto :EOF
if ERRORLEVEL 1 echo Copy successful & goto :EOF
if ERRORLEVEL 0 echo –no change– & goto :EOF
paradroid
fuente
8

Algunos de los carteles anteriores han perdido la sutileza de la máscara de bits. En particular, el paradroid ha pasado por alto que el error de nivel 3 indica una copia completamente exitosa.

Tenga en cuenta que el bit 0x01 si se establece indica que algunos archivos se han copiado incluso si hubo otras fallas. Por lo tanto, cualquier nivel de error impar siempre indica que al menos algunos archivos se han copiado. Tenga en cuenta también que el bit 0x02 simplemente indica que hay archivos en el destino que no están presentes en la fuente. Esto sucederá si se usa el modificador / E y los archivos se han eliminado de la fuente desde que se tomó una copia anterior. No debería suceder si se usa el modificador / MIR porque eso debería eliminar archivos en el destino para reflejar la fuente (pero no lo he probado).

Entonces, tanto el nivel de error 1 como el 3 indican una copia exitosa de archivos sin errores. También los niveles de error 0 y 2 indican que el destino está actualizado y que no se copiaron archivos.

Por lo que vale, se me ocurrió lo siguiente para mi copia de seguridad simple:

si el nivel de error 16 echo Respaldo falló - vea la razón arriba y pase a

si errorlevel 8 echo All is not well - copia de seguridad incompleta y listo

si errorlevel 4 echo All no está bien: algunos archivos no coinciden y se ha completado

si errorlevel 3 echo La copia de seguridad se completó con éxito y se completó

si errorlevel 2 echo La copia de seguridad ya está actualizada: no se copiaron archivos ni se realizó

si errorlevel 1 echo La copia de seguridad se completó con éxito y se completó

si errorlevel 0 echo La copia de seguridad ya está actualizada: no se copiaron los archivos y se realizó

Elegí no preocuparme por los archivos 'extra'.

No tengo idea de cuál es el error 'no coincidente' porque aún no ha sucedido, pero lo permití por si acaso.

GuestJohn
fuente
6

Estoy de acuerdo con Guest John: realmente solo quieres indicar un error si el resultado es en realidad 8 o superior.

así que para asignar un resultado de robocopy a un resultado 0 (éxito) o 1 (error), adecuado para usar en un trabajo de Agente SQL, estoy usando esto:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
  EXIT /B 1
ElectricLlama
fuente
2

Para TeamCity estoy usando esto y está funcionando bastante bien. Gracias a las aportaciones de MikeWyatt, DaoCacao y Yan Sklyarenko. Solo necesitaba ver un ejemplo de trabajo completo para ayudar a visualizar la respuesta.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0
Paul Oliver
fuente
1
Estoy usando una secuencia de comandos robocopy similar en mi evento POST-BUILD ... por lo que las bibliotecas dependientes se copian en el proyecto de aplicación .exe de consumo, al que solo se hace referencia a través del patrón de inversión de control / localizador de servicios.
bkwdesign
1

agregue cmd / c antes para gitlab ci.

cmd /c (robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LEQ 1 exit 0

de lo contrario, EXIT 0 cierra la canalización de CI en ese punto.

Scott Pepper
fuente
0

Un ejemplo aquí sobre cómo copiar archivos terminados de Visual Studio 2010+ a otra carpeta ya que Visual Studio espera un 0 no 1 en una buena copia.

cmd /c (robocopy $(TargetDir) X:\$(TargetName) $(TargetFileName) $(TargetFileName).config *.dll *.json *.xml /xx) ^& IF %ERRORLEVEL% LEQ 1 exit 0 
Glenn Perkins
fuente