Заставить ROBOCOPY вернуть «правильный» код выхода?

121

Можно ли попросить ROBOCOPY выйти с кодом выхода, который указывает на успех или неудачу?

Я использую ROBOCOPY как часть моих конфигураций сборки TeamCity, и необходимость добавлять шаг, чтобы просто заставить замолчать код выхода из ROBOCOPY, кажется мне глупой.

В основном я добавил это:

EXIT /B 0

к сценарию, который выполняется.

Тем не менее, это, конечно, маскирует любые реальные проблемы, которые ROBOCOPY вернет.

По сути, я хотел бы иметь коды выхода 0 для УСПЕХА и ненулевые для НЕИСПРАВНОСТИ вместо битовой маски, которую РОБОКОПИЯ возвращает сейчас.

Или, если у меня этого нет, есть ли простая последовательность командных команд, которая бы переводила битовую маску ROBOCOPY в аналогичное значение?

Lasse Vågsæther Karlsen
источник
2
Следует также отметить, что первые 8 кодов выхода (0-7), по-видимому, не являются ошибочными состояниями: stackoverflow.com/questions/16533843/psake-and-robocopy-failing
longda

Ответы:

47

Как здесь , Robocopy имеет следующие биты кода выхода, которые составляют код выхода:

0 × 10 Серьезная ошибка. Robocopy не копировал никаких файлов. Это либо ошибка использования, либо ошибка из-за недостаточных прав доступа к исходным или целевым каталогам.

0 × 08 Не удалось скопировать некоторые файлы или каталоги (возникли ошибки при копировании и превышен предел повторных попыток). Проверьте эти ошибки дальше.

0 × 04 Обнаружены некоторые несоответствующие файлы или каталоги. Изучите выходной журнал. Домашнее хозяйство, вероятно, необходимо.

0 × 02 Обнаружены некоторые дополнительные файлы или каталоги. Изучите выходной журнал. Некоторая уборка может быть необходима.

0 × 01 Один или несколько файлов были успешно скопированы (то есть поступили новые файлы).

0 × 00 Не было ошибок, и копирование не было выполнено. Деревья каталогов источника и назначения полностью синхронизированы.

Просто добавьте операторы if / else, EXIT /B 0когда возвращаемое значение равно 1 или, возможно, 0, и EXIT /B 1иначе. Даже если файлы могли быть скопированы, есть что-то не так, что потребует ручного вмешательства.

Даниэль Бек
источник
108

TechNet предлагает этот однострочный конвертировать код выхода в более традиционный код выхода:

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

Или это, чтобы полностью игнорировать код выхода (т.е. не волнует, провалился ли он или преуспел):

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

Однако обе приведенные выше команды прекратят выполнение сценария после выполнения робокопии. Это проблема особенно для сборок CI. Если вы хотите использовать robocopy в этом сценарии, вам нужно вручную установить код ошибки для нерелевантных кодов выхода. Ниже все коды ошибок ниже 8 будут переписаны без ошибок, и сценарий будет продолжен, если это возможно.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Ричард Дингвол
источник
8
Приятно. Требует скобки вокруг команды robocopy, но спас меня, используя скрипт-обертку.
TheCodeKing
Я не мог заставить этот однострочный текст работать как шаг сборки командной строки в TeamCity. Мне пришлось перенести это на отдельную строку. Я также добавил аргумент / B в команду выхода, хотя я не думаю, что это было необходимо.
MikeWyatt
Для развертывания Teamcity (и не только Teamcity) полезно набрать: IF %ERRORLEVEL% LEQ 3 set errorlevel=0и в следующей строке: if %errorlevel% neq 0 exit /b %errorlevel%(если пакетный файл состоит из нескольких операций, а не только robocopy), потому что коды ОК меньше 3. ss64.com/nt/robocopy -exit.html
DaoCacao
6
В TeamCity вы должны экранировать ERRORLEVELс двойным %%, например: %% ERRORLEVEL %%. В противном случае он считает это параметром сборки TeamCity.
Ян Скляренко
2
Что делает ^&? ss64 говорит, что убегает, но мне кажется, что не следует бежать?
mlhDev
19

Для запуска от Дженкинса нужны и то ( )и другое /B. Если вы хотите игнорировать уровень ошибки 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Филиппо Витале
источник
2
LSS 8 может быть даже лучше :)
Иван
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
Мокубай
источник
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
Paradroid
источник
8

Некоторые постеры выше пропустили тонкость битовой маски. В частности, Paradroid пропустил, что уровень ошибки 3 указывает на полностью успешную копию.

Обратите внимание, что бит 0x01, если установлен, указывает, что некоторые файлы были скопированы, даже если были другие сбои. Поэтому любые нечетные уровни ошибок всегда указывают, что по крайней мере некоторые файлы были скопированы. Также обратите внимание, что бит 0x02 просто указывает, что в месте назначения есть файлы, которых нет в источнике. Это произойдет, если используется ключ / E и файлы были удалены из источника с момента создания предыдущей копии. Это не должно происходить, если используется ключ / MIR, потому что это должно удалить файлы в месте назначения, чтобы отразить источник (но я не проверял это).

Таким образом, оба уровня ошибок 1 и 3 указывают на успешное копирование файлов без ошибок. Также уровни ошибок 0 и 2 указывают, что место назначения обновлено и файлы не были скопированы.

Для чего я стою, я придумал следующее для моей простой резервной копии:

если уровень ошибки 16 Эхо-резервное копирование не удалось - см. причину выше и перейти к

если errorlevel 8 echo Все не хорошо - резервное копирование не завершено и готово

если errorlevel 4 echo Все не хорошо - некоторые файлы не совпадают и готово

если errorlevel 3 echo Резервное копирование завершено успешно и выполнено

если errorlevel 2 echo Резервное копирование уже обновлено - файлы не скопированы и готово

если errorlevel 1 echo Резервное копирование завершено успешно и выполнено

если errorlevel 0 echo Резервное копирование уже обновлено - файлы не скопированы и не выполнено

Я решил не беспокоиться о «лишних» файлах.

Я понятия не имею, что такое «несоответствующая» ошибка, потому что она еще не произошла, но я допустила ее на всякий случай.

GuestJohn
источник
6

Я согласен с гостем Джоном - вы действительно хотите указать ошибку, только если результат на самом деле 8 или выше.

поэтому для сопоставления результата robocopy с результатом 0 (успех) или 1 (сбой), подходящим для использования в задании агента SQL, я использую это:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
  EXIT /B 1
ElectricLlama
источник
2

Для TeamCity я использую это, и это работает довольно хорошо. Благодаря вкладу Майка Уайетта, Дао Какао и Яна Скляренко. Мне просто нужно было увидеть полный рабочий пример, чтобы помочь визуализировать ответ.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0
Пол Оливер
источник
1
Я использую аналогичный сценарий robocopy в моем событии POST-BUILD .. поэтому зависимые библиотеки копируются в потребляющий проект приложения .exe - на который ссылаются только через шаблон поиска инверсии управления / службы.
bkwdesign,
1

добавьте cmd / c перед этим для gitlab ci.

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

в противном случае EXIT 0 закрывает конвейер CI в этой точке.

Скотт Пеппер
источник
0

Вот пример того, как скопировать готовые файлы из Visual Studio 2010+ в другую папку, так как Visual Studio ожидает 0, а не 1 на хорошей копии.

cmd /c (robocopy $(TargetDir) X:\$(TargetName) $(TargetFileName) $(TargetFileName).config *.dll *.json *.xml /xx) ^& IF %ERRORLEVEL% LEQ 1 exit 0 
Гленн Перкинс
источник