Conseguir que o ROBOCOPY retorne um código de saída "adequado"?

121

É possível solicitar ao ROBOCOPY que saia com um código de saída que indica sucesso ou falha?

Estou usando o ROBOCOPY como parte das minhas configurações de compilação do TeamCity, e ter que adicionar uma etapa para silenciar o código de saída do ROBOCOPY parece bobagem para mim.

Basicamente, eu adicionei isso:

EXIT /B 0

para o script que está sendo executado.

No entanto, é claro que isso oculta quaisquer problemas reais que o ROBOCOPY retornaria.

Basicamente, eu gostaria de ter códigos de saída 0 para SUCCESS e diferentes de zero para FAILURE, em vez da máscara de bits que ROBOCOPY retorna agora.

Ou, se eu não posso ter isso, existe uma sequência simples de comandos em lote que traduzem a máscara de bits do ROBOCOPY para um valor semelhante?

Lasse Vågsæther Karlsen
fonte
2
Também deve ser observado que os 8 primeiros códigos de saída (0-7) aparentemente não são estados de erro: stackoverflow.com/questions/16533843/psake-and-robocopy-failing
longda

Respostas:

47

Conforme aqui , o Robocopy possui os seguintes bits de código de saída que compõem o código de saída:

0 × 10 Erro grave. Robocopy não copiou nenhum arquivo. Esse é um erro de uso ou devido a privilégios de acesso insuficientes nos diretórios de origem ou destino.

0 × 08 Alguns arquivos ou diretórios não puderam ser copiados (ocorreram erros de cópia e o limite de novas tentativas foi excedido). Verifique esses erros ainda mais.

0 × 04 Alguns arquivos ou diretórios incompatíveis foram detectados. Examine o log de saída. O serviço de limpeza é provavelmente necessário.

0 × 02 Alguns arquivos ou diretórios extras foram detectados. Examine o log de saída. Algumas tarefas domésticas podem ser necessárias.

0 × 01 Um ou mais arquivos foram copiados com sucesso (ou seja, novos arquivos chegaram).

0 × 00 Nenhum erro ocorreu e nenhuma cópia foi feita. As árvores de diretórios de origem e destino são completamente sincronizadas.

Apenas adicione instruções if / else que EXIT /B 0quando o valor de retorno for 1 ou talvez 0 e EXIT /B 1caso contrário. Mesmo que os arquivos possam ter sido copiados, há algo errado que precisaria de intervenção manual.

Daniel Beck
fonte
108

O TechNet sugere este one-liner para converter o código de saída em um código de saída mais tradicional:

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

Ou isso para ignorar completamente o código de saída (ou seja, não se importe se ele falhou ou teve êxito):

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

No entanto, os dois comandos acima encerrarão um script após a execução da robocópia. Esse é um problema especialmente para compilações de IC. Se você deseja usar robocopy neste cenário, precisará definir o código de erro manualmente para códigos de saída irrelevantes. Abaixo, todos os códigos de erro abaixo de 8 serão reescritos sem nenhum erro e o script continuará, se possível.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Richard Dingwall
fonte
8
Agradável. Precisa de colchetes ao redor do comando robocopy, mas me salvou usando um script de wrapper.
TheCodeKing 02/03/12
Não consegui fazer com que essa linha única funcionasse como uma etapa de criação da linha de comando no TeamCity. Eu tive que movê-lo para uma linha separada. Também adicionei o argumento / B ao comando exit, embora eu não ache que isso foi necessário.
7118 MikeWyatt
Para a implantação do Teamcity (e não apenas do Teamcity), é útil digitar: IF %ERRORLEVEL% LEQ 3 set errorlevel=0e na próxima linha: if %errorlevel% neq 0 exit /b %errorlevel%(se o arquivo em lotes consistir em várias operações, não apenas na robocópia), porque os códigos OK são menores que 3. ss64.com/nt/robocopy -exit.html
DaoCacao
6
No TeamCity, você deve escapar do ERRORLEVELcom %%%, assim: %% ERRORLEVEL %%. Caso contrário, ele considera o parâmetro de construção do TeamCity.
Yan Sklyarenko 27/09/2013
2
O que ^&faz? ss64 diz escapes, mas parece-me que não deve ser escapado?
MlhDev 10/05
19

Executá-lo a partir de Jenkins precisa de ( )e /B. Se você deseja ignorar o nível de erro 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Filippo Vitale
fonte
2
LSS 8 poderia ser ainda melhor :)
Ivan
13

A partir desta página você pode adicionar uma seção ao seu arquivo de lote que usa a lista de códigos de erro para a saída dos erros e executar diferentes seções do 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
fonte
8

Eu uso isso:

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
fonte
8

Alguns pôsteres acima perderam a sutileza da máscara de bits. Em particular, o paradroid perdeu esse nível de erro 3, indicando uma cópia completamente bem-sucedida.

Observe que o bit 0x01, se definido, indica que alguns arquivos foram copiados mesmo se houver outras falhas. Portanto, quaisquer níveis de erro numerados ímpares sempre indicam que pelo menos alguns arquivos foram copiados. Observe também que o bit 0x02 simplesmente indica que existem arquivos no destino que não estão presentes na fonte. Isso acontecerá se a opção / E for usada e os arquivos tiverem sido excluídos da fonte desde que uma cópia anterior foi obtida. Isso não deve acontecer se a opção / MIR for usada, pois isso deve excluir os arquivos no destino para espelhar a fonte (mas eu não testei isso).

Portanto, o nível de erro 1 E 3 indica a cópia bem-sucedida de arquivos sem erros. Os níveis de erro 0 E 2 também indicam que o destino está atualizado e que nenhum arquivo foi copiado.

Por quanto vale, criei o seguinte para meu backup simples:

se errorlevel 16 echo Backup falhou - veja o motivo acima e foi feito

if errorlevel 8 echo Nem tudo está bem - o backup está incompleto e foi feito

if errorlevel 4 echo Nem tudo está bem - alguns arquivos foram incompatíveis e foram feitos

se errorlevel 3 echo Backup concluído com sucesso e foi concluído

if errorlevel 2 echo Backup já atualizado - nenhum arquivo copiado e pronto

se o nível de erro 1 eco backup concluído com êxito e for concluído

if errorlevel 0 echo Backup já atualizado - nenhum arquivo copiado e pronto

Eu escolhi não me preocupar com os arquivos 'extras'.

Eu não tenho idéia do que é o erro 'incompatível' porque ainda não aconteceu, mas eu o permiti por precaução.

GuestJohn
fonte
6

Concordo com o convidado John - você realmente deseja indicar apenas um erro se o resultado for realmente 8 ou superior.

para mapear um resultado de robocópia para um resultado 0 (êxito) ou 1 (falha), adequado para uso em um trabalho do SQL Agent, estou usando o seguinte:

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

Para o TeamCity, estou usando isso e está funcionando muito bem. Agradecemos a participação de MikeWyatt, DaoCacao e Yan Sklyarenko. Eu só precisava ver um exemplo completo de trabalho para ajudar a visualizar a resposta.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0
Paul Oliver
fonte
1
Estou usando um script de robocopy semelhante no meu evento POST-BUILD .. para que as bibliotecas dependentes sejam copiadas para o projeto de aplicativo .exe consumidor - que são referenciadas apenas por padrão de inversão de controle / localizador de serviço.
Bkwdesign 12/02
1

adicione cmd / c antes para o gitlab ci.

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

caso contrário, EXIT 0 fecha o pipeline do IC nesse ponto.

Scott Pepper
fonte
0

Um exemplo aqui sobre como copiar arquivos concluídos do Visual Studio 2010 ou superior para outra pasta, pois o Visual Studio espera um 0 e não 1 em uma boa cópia.

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