Mendapatkan ROBOCOPY untuk mengembalikan kode keluar yang "tepat"?

121

Apakah mungkin untuk meminta ROBOCOPY untuk keluar dengan kode keluar yang menunjukkan keberhasilan atau kegagalan?

Saya menggunakan ROBOCOPY sebagai bagian dari konfigurasi build TeamCity saya, dan harus menambahkan langkah untuk hanya membungkam kode keluar dari ROBOCOPY tampaknya konyol bagi saya.

Pada dasarnya, saya telah menambahkan ini:

EXIT /B 0

ke skrip yang sedang dijalankan.

Namun, ini tentu saja menutupi masalah nyata yang akan kembali oleh ROBOCOPY.

Pada dasarnya, saya ingin memiliki kode keluar 0 untuk SUKSES dan bukan-nol untuk KEGAGALAN alih-alih bit-mask yang dikembalikan ROBOCOPY sekarang.

Atau, jika saya tidak bisa memilikinya, apakah ada urutan sederhana dari perintah batch yang akan menerjemahkan bit-mask ROBOCOPY ke nilai yang sama?

Lasse Vågsæther Karlsen
sumber
2
Perlu juga dicatat bahwa 8 kode keluar pertama (0-7) tampaknya bukan status kesalahan: stackoverflow.com/questions/16533843/psake-and-robocopy-failing
longda

Jawaban:

47

Seperti di sini , Robocopy memiliki bit kode keluar berikut yang membentuk kode keluar:

0 × 10 Kesalahan serius. Robocopy tidak menyalin file apa pun. Ini adalah kesalahan penggunaan atau kesalahan karena hak akses yang tidak mencukupi pada direktori sumber atau tujuan.

0 × 08 Beberapa file atau direktori tidak dapat disalin (kesalahan penyalinan terjadi dan batas coba lagi terlampaui). Periksa kesalahan ini lebih lanjut.

0 × 04 Beberapa file atau direktori yang tidak cocok terdeteksi. Periksa log keluaran. Pembersihan mungkin diperlukan.

0 × 02 Beberapa file atau direktori tambahan terdeteksi. Periksa log keluaran. Pembersihan mungkin diperlukan.

0 × 01 Satu atau lebih file berhasil disalin (yaitu, file baru telah tiba).

0 × 00 Tidak ada kesalahan terjadi, dan tidak ada penyalinan. Pohon direktori sumber dan tujuan disinkronkan sepenuhnya.

Cukup tambahkan pernyataan if / else bahwa EXIT /B 0ketika nilai balik adalah 1 atau mungkin 0, dan EXIT /B 1sebaliknya. Bahkan jika file mungkin telah disalin, ada sesuatu yang salah yang memerlukan intervensi manual.

Daniel Beck
sumber
108

TechNet menyarankan one-liner ini untuk mengubah kode keluar menjadi kode keluar yang lebih tradisional:

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

Atau ini untuk mengabaikan kode keluar sepenuhnya (yaitu tidak peduli jika gagal atau berhasil):

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

Namun, kedua perintah di atas akan menghentikan skrip setelah robocopy dieksekusi. Ini adalah masalah terutama untuk membangun CI. Jika Anda ingin menggunakan robocopy dalam skenario ini, Anda perlu mengatur kode kesalahan secara manual untuk kode keluar yang tidak relevan. Di bawah ini, semua kode kesalahan di bawah 8 akan ditulis ulang tanpa kesalahan sama sekali, dan skrip akan dilanjutkan jika memungkinkan.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0
Richard Dingwall
sumber
8
Bagus. Membutuhkan tanda kurung di sekitar perintah robocopy, tetapi menyelamatkan saya menggunakan skrip wrapper.
TheCodeKing
Saya tidak bisa membuat one-liner ini berfungsi sebagai langkah membangun Command Line di TeamCity. Saya harus memindahkannya ke jalur terpisah. Saya juga menambahkan argumen / B ke perintah keluar, meskipun saya pikir itu tidak diperlukan.
MikeWyatt
Untuk penyebaran Teamcity (dan bukan hanya Teamcity), berguna untuk mengetik: IF %ERRORLEVEL% LEQ 3 set errorlevel=0dan pada baris berikutnya: if %errorlevel% neq 0 exit /b %errorlevel%(jika file batch terdiri dari beberapa operasi, tidak hanya robocopy), karena kode OK kurang dari 3. ss64.com/nt/robocopy -exit.html
DaoCacao
6
Di TeamCity, Anda harus menghindari ERRORLEVELdengan %% ganda, seperti ini: %% ERRORLEVEL %%. Kalau tidak, itu menganggapnya sebagai parameter build TeamCity.
Yan Sklyarenko
2
Apa yang ^&dilakukan? ss64 mengatakan lolos tetapi bagi saya sepertinya tidak harus melarikan diri?
mlhDev
19

Menjalankannya dari Jenkins membutuhkan keduanya ( )dan /B. Jika Anda ingin mengabaikan level kesalahan 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0
Filippo Vitale
sumber
2
LSS 8 mungkin lebih baik :)
Ivan
13

Dari halaman ini Anda dapat menambahkan bagian ke file batch Anda yang menggunakan daftar kode kesalahan untuk menghasilkan kesalahan dan menjalankan bagian kode yang berbeda:

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

Saya menggunakan ini:

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

Beberapa poster di atas telah melewatkan kehalusan topeng bit. Secara khusus paradroid telah melewatkan errorlevel 3 yang menunjukkan salinan yang sepenuhnya berhasil.

Perhatikan bahwa bit 0x01 jika diset menunjukkan bahwa beberapa file telah disalin bahkan jika ada kegagalan lainnya. Jadi setiap tingkat kesalahan ganjil selalu menunjukkan bahwa setidaknya beberapa file telah disalin. Perhatikan juga bahwa bit 0x02 hanya menunjukkan bahwa ada file di tujuan yang tidak ada di sumbernya. Ini akan terjadi jika saklar / E digunakan dan file telah dihapus dari sumber sejak salinan sebelumnya diambil. Seharusnya tidak terjadi jika saklar / MIR digunakan karena itu akan menghapus file di tujuan untuk mencerminkan sumber (tapi saya belum menguji ini).

Jadi kedua level 1 DAN 3 menunjukkan keberhasilan menyalin file tanpa kesalahan. Level error 0 AND 2 juga mengindikasikan bahwa tujuan sudah mutakhir dan tidak ada file yang disalin.

Untuk apa nilainya saya datang dengan yang berikut ini untuk cadangan sederhana saya:

jika errorlevel 16 echo Backup gagal - lihat alasan di atas & lakukan

jika errorlevel 8 echo All tidak baik - cadangan tidak lengkap & goto dilakukan

jika errorlevel 4 echo All tidak baik - beberapa file tidak cocok & dilakukan

jika errorlevel 3 echo Backup selesai dengan sukses & lakukan

jika errorlevel 2 echo Backup sudah diperbarui - tidak ada file yang disalin & dilakukan

jika errorlevel 1 echo Backup selesai dengan sukses & sudah selesai

jika errorlevel 0 echo Backup sudah diperbarui - tidak ada file yang disalin & dilakukan

Saya memilih untuk tidak repot dengan file 'ekstra'.

Saya tidak tahu apa kesalahan 'tidak cocok' karena itu belum terjadi tetapi saya mengizinkannya untuk berjaga-jaga.

GuestJohn
sumber
6

Saya setuju dengan Guest John - Anda benar-benar hanya ingin menunjukkan kesalahan jika hasilnya sebenarnya 8 atau lebih tinggi.

jadi untuk memetakan hasil robocopy ke hasil 0 (berhasil) atau 1 (gagal), cocok untuk digunakan dalam pekerjaan SQL Agent, saya menggunakan ini:

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

Untuk TeamCity saya menggunakan ini dan itu berfungsi dengan baik. Terima kasih atas masukan dari MikeWyatt, DaoCacao, dan Yan Sklyarenko. Saya hanya perlu melihat contoh yang berfungsi penuh untuk membantu memvisualisasikan jawabannya.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0
Paul Oliver
sumber
1
Saya menggunakan skrip robocopy serupa di acara POST-BUILD saya .. jadi pustaka yang tergantung disalin ke dalam proyek aplikasi .exe yang mengkonsumsi - yang hanya direferensikan melalui pola locator inversi-of-control / service locator.
bkwdesign
1

tambahkan cmd / c sebelum untuk gitlab ci.

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

jika EXIT 0 menutup pipa CI pada saat itu.

Scott Pepper
sumber
0

Contoh di sini tentang cara menyalin file jadi dari Visual Studio 2010+ ke folder lain sebagai Visual Studio mengharapkan 0 bukan 1 pada salinan yang baik.

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