Bắt ROBOCOPY để trả lại mã thoát ra phù hợp với tên lửa nào?


121

Có thể yêu cầu ROBOCOPY thoát với mã thoát cho biết thành công hay thất bại?

Tôi đang sử dụng ROBOCOPY như một phần trong cấu hình bản dựng TeamCity của mình và việc phải thêm một bước để chỉ tắt mã thoát khỏi ROBOCOPY có vẻ ngớ ngẩn đối với tôi.

Về cơ bản, tôi đã thêm điều này:

EXIT /B 0

đến kịch bản đang được chạy.

Tuy nhiên, điều này tất nhiên che giấu mọi vấn đề thực sự mà ROBOCOPY sẽ trả lại.

Về cơ bản, tôi muốn có mã thoát là 0 cho THÀNH CÔNG và khác không cho FAILURE thay vì mặt nạ bit mà ROBOCOPY trả về bây giờ.

Hoặc, nếu tôi không thể có điều đó, có một chuỗi đơn giản các lệnh bó sẽ dịch mặt nạ bit của ROBOCOPY thành một giá trị tương tự không?


2
Cũng cần lưu ý rằng 8 mã thoát đầu tiên (0-7) rõ ràng không phải là trạng thái lỗi: stackoverflow.com/questions/16533843/psake-and-robocopy-fending
longda 12/214

Câu trả lời:


47

Theo ở đây , Robocopy có các bit mã thoát sau đây tạo nên mã thoát:

0 × 10 Lỗi nghiêm trọng. Robocopy đã không sao chép bất kỳ tập tin. Đây là lỗi sử dụng hoặc lỗi do không đủ đặc quyền truy cập trên các thư mục nguồn hoặc đích.

0 × 08 Một số tệp hoặc thư mục không thể được sao chép (xảy ra lỗi sao chép và vượt quá giới hạn thử lại). Kiểm tra các lỗi này hơn nữa.

0 × 04 Một số tệp hoặc thư mục không khớp được phát hiện. Kiểm tra nhật ký đầu ra. Dịch vụ dọn phòng có lẽ là cần thiết.

0 × 02 Một số tệp hoặc thư mục bổ sung đã được phát hiện. Kiểm tra nhật ký đầu ra. Một số vệ sinh có thể cần thiết.

0 × 01 Một hoặc nhiều tệp đã được sao chép thành công (nghĩa là các tệp mới đã đến).

0 × 00 Không có lỗi xảy ra và không có bản sao nào được thực hiện. Cây thư mục nguồn và đích được đồng bộ hóa hoàn toàn.

Chỉ cần thêm if / other tuyên bố rằng EXIT /B 0khi giá trị trả về là 1 hoặc có thể là 0, và EXIT /B 1nếu không. Ngay cả khi các tập tin có thể đã được sao chép, có một cái gì đó sai cần can thiệp thủ công.


108

TechNet đề xuất một lớp lót này để chuyển đổi mã thoát thành mã thoát truyền thống hơn:

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

Hoặc điều này để bỏ qua hoàn toàn mã thoát (nghĩa là không quan tâm nếu nó thất bại hoặc thành công):

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

Tuy nhiên, cả hai lệnh trên sẽ chấm dứt một tập lệnh sau khi bản sao lưu được thực thi. Đây là một vấn đề đặc biệt đối với các bản dựng CI. Nếu bạn muốn sử dụng robocopy trong kịch bản này, bạn cần đặt mã lỗi theo cách thủ công cho các mã thoát không liên quan. Dưới đây, tất cả các mã lỗi dưới 8 sẽ được viết lại thành không có lỗi nào, và tập lệnh sẽ được tiếp tục nếu có thể.

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

8
Đẹp. Cần dấu ngoặc quanh lệnh robocopy, nhưng đã lưu tôi bằng cách sử dụng tập lệnh bao bọc.
TheCodeKing

Tôi không thể có được lớp lót này hoạt động như một bước xây dựng Dòng lệnh trong TeamCity. Tôi đã phải di chuyển nó đến một dòng riêng biệt. Tôi cũng đã thêm đối số / B vào lệnh exit, mặc dù tôi không nghĩ rằng điều đó là bắt buộc.
MikeWyatt

Đối với triển khai Teamcity (và không chỉ Teamcity), rất hữu ích khi nhập: IF %ERRORLEVEL% LEQ 3 set errorlevel=0và trên dòng tiếp theo: if %errorlevel% neq 0 exit /b %errorlevel%(nếu tệp bó bao gồm một số thao tác, không chỉ sao chép), vì mã OK ít hơn 3. ss64.com/nt/robocopy -exit.html
DaoCacao

6
Trong TeamCity, bạn nên thoát ERRORLEVELvới tỷ lệ %%, như thế này: %% ERRORLEVEL %%. Mặt khác, nó coi nó là tham số xây dựng TeamCity.
Yan Sklyarenko

2
Làm gì ^&? ss64 nói trốn thoát nhưng dường như với tôi nó không nên trốn thoát?
mlhDev

19

Chạy nó từ Jenkins cần cả ( )/B. Nếu bạn muốn bỏ qua mức lỗi 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0

2
LSS 8 có thể còn tốt hơn :)
Ivan

13

Từ trang này, bạn có thể thêm một phần vào tệp bó sử dụng danh sách mã lỗi để xuất lỗi và chạy các phần mã khác nhau:

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

Tôi sử dụng cái này:

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

8

Một số áp phích ở trên đã bỏ lỡ sự tinh tế của mặt nạ bit. Cụ thể là paradroid đã bỏ lỡ rằng errorlevel 3 chỉ ra một bản sao hoàn toàn thành công.

Lưu ý rằng bit 0x01 nếu được đặt chỉ ra rằng một số tệp đã được sao chép ngay cả khi có các lỗi khác. Vì vậy, bất kỳ lỗi số lẻ nào luôn chỉ ra rằng ít nhất một số tệp đã được sao chép. Cũng lưu ý rằng bit 0x02 chỉ đơn giản chỉ ra rằng có các tệp tại đích không có trong nguồn. Điều này sẽ xảy ra nếu công tắc / E được sử dụng và các tệp đã bị xóa khỏi nguồn kể từ khi bản sao trước đó được lấy. Điều này không xảy ra nếu công tắc / MIR được sử dụng vì điều đó sẽ xóa các tệp tại đích để phản chiếu nguồn (nhưng tôi chưa kiểm tra điều này).

Vì vậy, cả errorlevel 1 VÀ 3 chỉ ra việc sao chép thành công các tệp không có lỗi. Ngoài ra các lỗi 0 và 2 chỉ ra rằng đích đến được cập nhật và không có tệp nào được sao chép.

Để biết giá trị của nó, tôi đã đưa ra những điều sau đây cho bản sao lưu đơn giản của mình:

nếu errorlevel 16 echo Sao lưu thất bại - xem lý do ở trên & goto xong

if errorlevel 8 echo Tất cả đều không tốt - sao lưu chưa hoàn tất & đã hoàn tất

if errorlevel 4 echo Tất cả đều không tốt - một số tệp đã không khớp và hoàn thành

nếu errorlevel 3 echo Sao lưu thành công & goto xong

if errorlevel 2 echo Sao lưu đã được cập nhật - không có tệp nào được sao chép & goto

if errorlevel 1 echo Sao lưu hoàn tất thành công & goto xong

if errorlevel 0 echo Sao lưu đã được cập nhật - không có tệp nào được sao chép & goto

Tôi đã chọn không bận tâm về các tập tin 'thêm'.

Tôi không biết lỗi 'không khớp' là gì vì nó chưa xảy ra nhưng tôi đã cho phép nó chỉ trong trường hợp.


6

Tôi đồng ý với Guest John - bạn thực sự chỉ muốn chỉ ra lỗi nếu kết quả thực sự là 8 hoặc cao hơn.

Vì vậy, để ánh xạ kết quả sao chép thành kết quả 0 (thành công) hoặc 1 (thất bại), phù hợp để sử dụng trong công việc Tác nhân SQL, tôi đang sử dụng:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
  EXIT /B 1

2

Đối với TeamCity tôi đang sử dụng cái này và nó hoạt động khá tốt. Nhờ vào đầu vào từ MikeWyatt, DaoCacao và Yan Sklyarenko. Tôi chỉ cần xem một ví dụ hoạt động đầy đủ để giúp hình dung câu trả lời.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0

1
Tôi đang sử dụng một kịch bản sao chép tương tự trong sự kiện POST-BUILD của mình .. vì vậy các thư viện phụ thuộc được sao chép vào dự án ứng dụng .exe tiêu thụ - vốn chỉ được tham chiếu qua mẫu định vị dịch vụ đảo ngược / điều khiển dịch vụ.
bkwdesign

1

thêm cmd / c trước nó cho gitlab ci.

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

mặt khác, EXIT 0 đóng đường ống CI tại điểm đó.


0

Một ví dụ ở đây về cách sao chép các tệp đã hoàn thành từ Visual Studio 2010+ sang một thư mục khác vì Visual Studio mong đợi 0 không 1 trên một bản sao tốt.

cmd /c (robocopy $(TargetDir) X:\$(TargetName) $(TargetFileName) $(TargetFileName).config *.dll *.json *.xml /xx) ^& IF %ERRORLEVEL% LEQ 1 exit 0 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.