Czy ROBOCOPY zwraca „prawidłowy” kod wyjścia?

121

Czy można poprosić ROBOCOPY o wyjście z kodem wyjścia wskazującym powodzenie lub niepowodzenie?

Korzystam z ROBOCOPY jako części konfiguracji kompilacji TeamCity, a konieczność dodania kroku wyciszenia kodu wyjścia z ROBOCOPY wydaje mi się głupia.

Zasadniczo dodałem to:

EXIT /B 0

do uruchamianego skryptu.

Jednak to oczywiście maskuje wszelkie rzeczywiste problemy, które powróci ROBOCOPY.

Zasadniczo chciałbym mieć kody wyjścia 0 dla SUKCESU i niezerowe dla BŁĘDU zamiast maski bitowej, którą ROBOCOPY zwraca teraz.

Lub, jeśli nie mogę tego mieć, czy istnieje prosta sekwencja poleceń wsadowych, która przekształciłaby maskę bitową ROBOCOPY na podobną wartość?

Lasse Vågsæther Karlsen
źródło
2
Należy również zauważyć, że pierwszych 8 kodów wyjścia (0–7) najwyraźniej nie oznacza stanów błędu: stackoverflow.com/questions/16533843/psake-and-robocopy-failing
longda

Odpowiedzi:

47

Zgodnie z tym , Robocopy ma następujące bity kodu wyjścia, które składają się na kod wyjścia:

0 × 10 Poważny błąd. Robocopy nie skopiował żadnych plików. Jest to błąd użytkowania lub błąd wynikający z niewystarczających uprawnień dostępu do katalogu źródłowego lub docelowego.

0 × 08 Niektórych plików lub katalogów nie można skopiować (wystąpiły błędy kopiowania i przekroczono limit ponownych prób). Sprawdź te błędy dalej.

0 × 04 Wykryto niektóre niedopasowane pliki lub katalogi. Sprawdź dziennik wyjściowy. Sprzątanie jest prawdopodobnie konieczne.

0 × 02 Wykryto niektóre dodatkowe pliki lub katalogi. Sprawdź dziennik wyjściowy. Może być potrzebne sprzątanie.

0 × 01 Jeden lub więcej plików zostało pomyślnie skopiowanych (tzn. Przybyły nowe pliki).

0 × 00 Nie wystąpiły błędy i nie przeprowadzono kopiowania. Drzewa katalogów źródłowych i docelowych są całkowicie zsynchronizowane.

Wystarczy dodać instrukcje if / else, że EXIT /B 0gdy zwracana wartość wynosi 1 lub może 0, i w EXIT /B 1przeciwnym razie. Nawet jeśli pliki mogły zostać skopiowane, istnieje coś złego, co wymagałoby ręcznej interwencji.

Daniel Beck
źródło
108

TechNet sugeruje, aby ten linijka przekształciła kod wyjścia w bardziej tradycyjny kod wyjścia:

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

Lub to całkowicie zignorować kod wyjścia (tj. Nie przejmuj się, czy nie powiódł się lub powiódł):

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

Jednak obie powyższe komendy zakończą skrypt po wykonaniu robocopy. Jest to problem szczególnie w przypadku kompilacji CI. Jeśli chcesz użyć robocopy w tym scenariuszu, musisz ręcznie ustawić kod błędu dla nieistotnych kodów wyjścia. Poniżej wszystkie kody błędów poniżej 8 zostaną przepisane bezbłędnie, a skrypt będzie kontynuowany, jeśli to możliwe.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Richard Dingwall
źródło
8
Miły. Potrzebuje nawiasów wokół polecenia robocopy, ale uratował mnie za pomocą skryptu opakowania.
TheCodeKing
Nie udało mi się sprawić, by ten liner działał jako krok kompilacji w wierszu poleceń w TeamCity. Musiałem przenieść go do osobnej linii. Dodałem również argument / B do komendy exit, chociaż nie sądzę, aby było to wymagane.
MikeWyatt,
W przypadku wdrożenia Teamcity (i nie tylko Teamcity) przydatne jest wpisanie: IF %ERRORLEVEL% LEQ 3 set errorlevel=0i w następnym wierszu: if %errorlevel% neq 0 exit /b %errorlevel%(jeśli plik wsadowy składa się z kilku operacji, nie tylko robocopy), ponieważ kody OK są mniejsze niż 3. ss64.com/nt/robocopy -exit.html
DaoCacao,
6
W TeamCity powinieneś uciec ERRORLEVELz podwójnym %%, na przykład: %% ERRORLEVEL %%. W przeciwnym razie uważa to za parametr kompilacji TeamCity.
Yan Sklyarenko
2
Czego ^&zrobić? ss64 mówi, że ucieka, ale wydaje mi się, że nie należy tego robić?
mlhDev
19

Uruchomienie go z Jenkins wymaga zarówno ( )i /B. Jeśli chcesz zignorować poziom błędu 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Filippo Vitale
źródło
2
LSS 8 może być jeszcze lepszy :)
Ivan
13

Na tej stronie możesz dodać sekcję do pliku wsadowego, która używa listy kodów błędów do generowania błędów i uruchamiania różnych sekcji kodu:

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
źródło
8

Używam tego:

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
źródło
8

W niektórych plakatach powyżej brakuje subtelności maski bitowej. W szczególności paradroid nie zauważył, że poziom błędu 3 wskazuje na całkowicie udaną kopię.

Zauważ, że bit 0x01, jeśli ustawiony, wskazuje, że niektóre pliki zostały skopiowane, nawet jeśli wystąpiły inne awarie. Zatem wszelkie niepoprawne poziomy błędów zawsze wskazują, że przynajmniej niektóre pliki zostały skopiowane. Zauważ również, że bit 0x02 po prostu wskazuje, że w miejscu docelowym znajdują się pliki, których nie ma w źródle. Stanie się tak, jeśli zostanie użyty przełącznik / E, a pliki zostały usunięte ze źródła od momentu pobrania poprzedniej kopii. Nie powinno się to zdarzyć, jeśli używany jest przełącznik / MIR, ponieważ powinien on usuwać pliki w miejscu docelowym, aby wykonać kopię lustrzaną źródła (ale nie przetestowałem tego).

Zatem oba poziomy błędu 1 i 3 wskazują na udane kopiowanie plików bez błędów. Również poziomy błędu 0 i 2 wskazują, że miejsce docelowe jest aktualne i nie skopiowano żadnych plików.

Dla mojej wartości wymyśliłem następujące dla mojej prostej kopii zapasowej:

jeśli poziom błędu 16 echo Tworzenie kopii zapasowej nie powiodło się - patrz powyższy powód i gotowe

jeśli poziom błędu 8 echo Wszystko nie jest dobrze - tworzenie kopii zapasowej niekompletne i gotowe

jeśli poziom błędu 4 echo Wszystko nie jest dobrze - niektóre pliki były niedopasowane i gotowe

jeśli poziom błędu 3 echo Tworzenie kopii zapasowej zakończyło się powodzeniem i gotowe

jeśli błąd poziomu 2 echo Kopia zapasowa jest już aktualna - żadne pliki nie zostały skopiowane i gotowe

jeśli poziom błędu 1 echo Tworzenie kopii zapasowej zakończyło się powodzeniem i gotowe

jeśli poziom błędu 0 echo Tworzenie kopii zapasowej jest już aktualne - żadne pliki nie zostały skopiowane i gotowe

Zdecydowałem się nie przejmować „dodatkowymi” plikami.

Nie mam pojęcia, czym jest błąd „niedopasowany”, ponieważ jeszcze się nie zdarzyło, ale na wszelki wypadek pozwoliłem na to.

GuestJohn
źródło
6

Zgadzam się z gościem Johnem - naprawdę chcesz wskazać błąd tylko wtedy, gdy wynik wynosi w rzeczywistości 8 lub więcej.

więc aby zmapować wynik robocopy na wynik 0 (sukces) lub 1 (błąd), odpowiedni do użycia w zadaniu agenta SQL, używam tego:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
  EXIT /B 1
ElectricLlama
źródło
2

W TeamCity używam tego i działa całkiem dobrze. Dzięki wkładowi MikeWyatt, DaoCacao i Yan Sklyarenko. Musiałem tylko zobaczyć pełny działający przykład, aby pomóc w wizualizacji odpowiedzi.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0
Paul Oliver
źródło
1
Korzystam z podobnego skryptu robocopy w moim zdarzeniu POST-BUILD. Dlatego biblioteki zależne są kopiowane do projektu aplikacji .exe, do którego odwołuje się tylko wzorzec inwersji kontroli / lokalizatora usług.
bkwdesign
1

dodaj cmd / c przed nim dla gitlab ci.

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

w przeciwnym razie EXIT 0 zamyka potok CI w tym punkcie.

Scott Pepper
źródło
0

Oto przykład, jak skopiować gotowe pliki z Visual Studio 2010+ do innego folderu, ponieważ Visual Studio oczekuje na 0, a nie 1 na dobrej kopii.

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