让 ROBOCOPY 返回“正确的”退出代码?

Las*_*sen 139 robocopy exit-code

是否可以要求 ROBOCOPY 以指示成功或失败的退出代码退出?

我正在使用 ROBOCOPY 作为我的 TeamCity 构建配置的一部分,并且不得不添加一个步骤来使 ROBOCOPY 的退出代码静音对我来说似乎很愚蠢。

基本上,我已经添加了这个:

EXIT /B 0
Run Code Online (Sandbox Code Playgroud)

到正在运行的脚本。

然而,这当然掩盖了 ROBOCOPY 会返回的任何实际问题。

基本上,我希望成功的退出代码为 0,失败的退出代码为非零,而不是 ROBOCOPY 现在返回的位掩码。

或者,如果我不能这样做,是否有一个简单的批处理命令序列可以将 ROBOCOPY 的位掩码转换为类似的值?

小智 134

TechNet 建议使用这种单行代码将退出代码转换为更传统的退出代码:

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LEQ 1 exit 0
Run Code Online (Sandbox Code Playgroud)

或者这完全忽略退出代码(即不关心它是失败还是成功):

(robocopy c:\dirA c:\dirB *.*) ^& exit 0
Run Code Online (Sandbox Code Playgroud)

但是,上述两个命令都将在 robocopy 执行后终止脚本。这是一个特别是对于 CI 构建的问题。如果你想在这种场景下使用robocopy,你需要为不相关的退出代码手动设置错误代码。下面,8以下的所有错误代码都将被重写为完全没有错误,如果可能,脚本将继续。

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Run Code Online (Sandbox Code Playgroud)

  • 好的。在 robocopy 命令周围需要括号,但使用包装脚本保存了我。 (8认同)
  • 在 TeamCity 中,您应该使用双 %% 转义 `ERRORLEVEL`,如下所示:%%ERRORLEVEL%%。否则,它会将其视为 TeamCity 构建参数。 (6认同)
  • `^&` 有什么作用?[ss64](https://ss64.com/nt/syntax-esc.html#escape) 说转义,但在我看来它不应该被转义? (3认同)

Dan*_*eck 50

根据此处,Robocopy 具有以下构成退出代码的退出代码位:

0×10 严重错误。Robocopy 没有复制任何文件。这要么是使用错误,要么是由于对源目录或目标目录的访问权限不足而导致的错误。

0×08 无法复制某些文件或目录(发生复制错误并超出重试限制)。进一步检查这些错误。

0×04 检测到一些不匹配的文件或目录。检查输出日志。家政服务可能是必要的。

0×02 检测到一些额外的文件或目录。检查输出日志。可能需要一些家政服务。

0×01 一个或多个文件复制成功(即有新文件到达)。

0×00 未发生错误,未进行复制。源目录树和目标目录树完全同步。

只需添加 if/else 语句,EXIT /B 0当返回值为 1 或可能为 0 时,EXIT /B 1否则。即使文件可能已被复制,也存在需要手动干预的错误。

  • 我认为这是 Robocopy 中的一个错误,并已在此处报告:https://github.com/MicrosoftDocs/windowsserverdocs.de-de/issues/49 (2认同)

Fil*_*ale 20

从 Jenkins 运行它需要( )/B。如果要忽略错误级别 1、2、3、4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Run Code Online (Sandbox Code Playgroud)

  • LSS 8 可能会更好:) (2认同)
  • 我没有足够的代表来回答,但这是实际的答案:`(Setlocal EnableDelayedExpansion) && (robocopy <...>) || 如果!错误级别!LSS 8(光盘)` (2认同)

Mok*_*bai 13

此页面中,您可以向批处理文件添加一个部分,该部分使用错误代码列表来输出错误并运行不同的代码部分:

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
Run Code Online (Sandbox Code Playgroud)


小智 9

上面的一些海报错过了位掩码的微妙之处。特别是 paradroid 错过了错误级别 3 表示完全成功的副本。

请注意,如果设置了位 0x01,则表示即使存在其他故障,某些文件也已被复制。因此,任何奇数错误级别总是表明至少有一些文件已被复制。另请注意,位 0x02 仅表示目标中存在源中不存在的文件。如果使用了 /E 开关,并且自上次复制后文件已从源中删除,则会发生这种情况。如果使用 /MIR 开关,则不会发生这种情况,因为这应该删除目标处的文件以镜像源(但我尚未对此进行测试)。

因此,错误级别 1 和 3 都表示成功复制文件且没有错误。此外,错误级别 0 和 2 表示目标是最新的,并且没有复制任何文件。

为了它的价值,我为我的简单备份想出了以下内容:

if errorlevel 16 echo Backup failed - see reason above & goto done

if errorlevel 8 echo All is not well - backup incomplete & goto done

if errorlevel 4 echo All is not well - some files were mismatched & goto done

if errorlevel 3 echo Backup completed successfully & goto done

if errorlevel 2 echo Backup already up to date - no files copied & goto done

if errorlevel 1 echo Backup completed successfully & goto done

if errorlevel 0 echo Backup already up to date - no files copied & goto done
Run Code Online (Sandbox Code Playgroud)

我选择不理会“额外”文件。

我不知道“不匹配”错误是什么,因为它还没有发生,但我允许它以防万一。


par*_*oid 8

我用这个:

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
Run Code Online (Sandbox Code Playgroud)


Ele*_*ama 7

我同意来宾约翰 - 如果结果实际上是 8 或更高,你真的只想指出一个错误。

因此,要将 robocopy 结果映射到 0(成功)或 1(失败)结果,适用于 SQL 代理作业,我使用的是:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
  EXIT /B 1
Run Code Online (Sandbox Code Playgroud)