jonny83
Goto Top

CMD robocopy in for Schleife. Errorlevel ist leider immer 0 bei Fehler und bei Erfolg von robocopy

Robocopy liefert in aller Regel einen Errorlevel Wert zurück. Durch die FOR Schleife erhalte ich aber immer "errorlevel = 0"

Hallo zusammen,

Robocopy ist für mich ein bekanntes Tool welches ich auch häufig einsetze.

Aktuell versuche ich einen Ordner (...Skripte) von mehreren Servern zu kopieren.

Damit ich jetzt nicht x-mal robocopy server1(2,3,4,...) Quelle Ziel Parameter eingeben muss habe ich eine *.txt Datei in der ich alle Server aufliste.

Das funktioniert alles fehlerfrei!

Einzigstens Problem:

Wenn Robocopy bei einem der Server ein Problem hat (z.B. Zugriff verweigert....Datei nicht gefunden....blaaa) wird der Wert "Errorlevel" in meine CMD Box NICHT mit dem Robocopy errorlog überschrieben sondern bleibt immer ´0´

Sicher hängt das mit meiner FOR xxxxxyyyyyzzzzz Schleife zusammen die ja immer ´0´ zurück liefert. (Die For schleife funktioniert ja auch ... )

Nur wie bekomme ich das gelöst? Wie komm ich an den errorlog Wert von robocopy ran?

Wie kann ich prüfen lassen ob einer der Server, aus der *.txt, mit robocopy einen Fehler meldete?

Wenn ich den realen robocopy Befehl ausführen erhalte ich meinen korrekten robocopy errorlog. Aber ich brauch das ganze ja in der Schleife ... ok los gehts:

Ich hoffe ihr könnt hier helfen.

Vorweg - Ergebnis von der BAT:
BAT ANFANG

C:\>C:\skripte\cmd\Skripte_Backup\Skripte_Backup.cmd
Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

Log File : C:\skripte\logs\Skripte_Backup.log

C:\>
BAT ENDE

/

Skript Anfang

@echo off
echo.

:: Skript für die Sicherung der Skripte auf den Batchservern
:: von C:\skripte nach \\server1\Batchserver_skripte$

:: Variablen setzen
set "MailEXE=C:\skripte\bin\Maildienst\bmail.exe"
set "ABS=Batchserver@domain.dom"
set "Mailtxt=C:\skripte\cmd\server1_software_backup\EMail.txt"
set "temptxt=C:\skripte\temp\tempskripte.txt"
set "Quelle=\\%%i\skripte$\"
set "Ziel=\\server1\Batchserver_skripte$\%%i\"
set "Mailsrv=exchange.domain.dom"
set "RCPT=pruef1@domain.dom"
set "Subj=Backup von Skripte$ auf %%i hat einen Fehler gemeldet!"
set "Liste=C:\skripte\bin\Batchserverliste\alle_Batchserver.txt"
set "LOG=C:\skripte\logs\Skripte_Backup.log"

:: Löschen der alten LOGs
del /q "%LOG%"
del /q "%temptxt%"

:: Sicherung von Software$
for /f "usebackq delims=" %%i in ("%Liste%") do robocopy %Quelle% %Ziel% *.* /COPY:D /MIR /W:0 /R:0 /LOG+:%LOG% & echo %errorlevel%

:: Auswertung der Rückmeldung von Robocopy
if not errorlevel 0 echo FEHLER aufgetreten >> %LOG% & goto MAILVERSAND
:: for /f "usebackq delims=" %%i in ("%Liste%") do if not %Fehler%=0
:: echo Der Wert des Errorlevels ist %errorlevel% >> %LOG%
:: if errorlevel 16 echo *FATAL ERROR* >> %LOG% & goto MAILVERSAND
:: if errorlevel 15 echo FAIL MISM XTRA COPY >> %LOG% & goto MAILVERSAND
:: if errorlevel 14 echo FAIL MISM XTRA >> %LOG% & goto MAILVERSAND
:: if errorlevel 13 echo FAIL MISM COPY >> %LOG% & goto MAILVERSAND
:: if errorlevel 12 echo FAIL MISM >> %LOG% & goto MAILVERSAND
:: if errorlevel 11 echo FAIL XTRA COPY >> %LOG% & goto MAILVERSAND
:: if errorlevel 10 echo FAIL XTRA >> %LOG% & goto MAILVERSAND
:: if errorlevel 9 echo FAIL COPY >> %LOG% & goto MAILVERSAND
:: if errorlevel 8 echo FAIL >> %LOG% & goto MAILVERSAND
goto END

:: Bei einem Fehler wird die E-Mail versendet!
:MAILVERSAND
type %Mailtxt% >> %temptxt%
type %LOG% >> %temptxt%
%MailEXE% -s %Mailsrv% -t %RCPT% -f %ABS% -h -a "%Subj%" -m %temptxt% -c
del %temptxt%

:END

Skript Ende

Content-ID: 149721

Url: https://administrator.de/contentid/149721

Ausgedruckt am: 05.11.2024 um 07:11 Uhr

Karo
Karo 25.08.2010 um 15:34:54 Uhr
Goto Top
Hoi,

vielleicht solltest Du echo %errorlevel% in der Schleife in eine Datei schreiben und diese dann nach Errorlevel-Werten abarbeiten.
So wie bisher wird Dein Echo %errorlevel% ausgewertet und das ist ja eigentlich immer erfolgreich.

Karo
jonny83
jonny83 25.08.2010 um 15:39:20 Uhr
Goto Top
Hi,

betrachten wir diese Zeilen:

for /f "usebackq delims=" %%i in ("%Liste%") do robocopy %Quelle% %Ziel% *.* /COPY:D /MIR /W:0 /R:0 /LOG+:%LOG% & echo %errorlevel%

hier bearbeite ich den Errorlog doch in der Schleife ... oder nicht?

OK - die Umleitung in eine Datei fehlt - aber spielt ja keine Rolle wenn er eh nur ´0´ rein schreibt ...

Wie würdest du das schreiben?
jonny83
jonny83 25.08.2010 um 15:52:09 Uhr
Goto Top
es muss ja auch nicht der Errorlevel sein ... ich will letztlich nur irgendwie prüfen können WANN und vor allem OB ein Fehler aufgetreten ist.

Auch habe ich schon überlegt die %LOG% nach "ERROR" zu durchsuchen. Da finde ich auch "ERROR 5" <-- aber das ist mein Fallbeispiel! Ich habe in dem Ziel bei einem Ordner die Schreibrechte für den Bat-User weg genommen. Also ist ERROR 5 der Fatal Error und nicht grad ein gutes Beispiel. Aber ich habe einen Fehler den ich erzwinge um eben zu prüfen was der errorlog macht.

Ach ja - die %LOG% kann ich nicht nach ERROR 5 durchsuchen weil ich auch Dateien habe die so heissen könnten .... ich brauch nen stabilen / zuverlässigen Rückgabewert - und da ist ERROR 5 irgendwo in der %LOG% nicht gut ^^

SOS .... *heul* - so ein dummes Problem echt ....
Karo
Karo 25.08.2010 um 15:58:03 Uhr
Goto Top
nun, es gibt da sicher verschiedene Ansätze.
Ersteinmal fährst Du in Deinem Beispiel eine Schleife und gibst jedesmal in der Console den Errorlevel aus. Das bis zum Ende der Textdatei. Erst nach dem letzten wertest Du Errorlevel aus! Und das wiederum vom letzten Befehl und der ist Echo %Errorlevel%. Der ist natürlich erfolgreich, sodass Du 0 bekommst.
Was Du aber machen willst ist, für jeden Robocopy Job ein Errorlevel auszugeben und wenn einer davon falsch ist, dann Meldung.
Ich würde es vielleicht so machen, das das ... & echo %Errolevel% geändert wird in z.B. Echo <SERVERNAME AUS LISTE> %ERRORLEVEL% >>ERRORSVC.LOG zu ändern.
Wenn alle Jobs durch sind das ERRORSVC.LOG auswerten und für jeden <SERVERNAME AUS LISTE> größer als 0 eine Mail zu schicken. So hätte man gleich einen Ansatz wo was geklemmt hat.

Karo
jonny83
jonny83 25.08.2010 um 16:20:42 Uhr
Goto Top
Hi,

also gut - ich habe das nochmal getestet:

for /f "usebackq delims=" %%i in ("%Liste%") do robocopy %Quelle% %Ziel% *.* /COPY:D /MIR /W:0 /R:0 /LOG+:%LOG% & echo "HALLO" %%i %ERRORLEVEL% >> %LOG%

ich packe hinten dran - also nach dem do .... robocopy .... blaaaa .... ein & echo "HALLO" %%i %ERRORLEVEL% >> %LOG%

jetzt durchsuche ich das %LOG% nach "HALLO" und finde auch jeden Server aber mit dem Errorlevel ´0´

also es klappt nach wie vor leider nicht ...

vielleicht kannst du mal hier editieren - also mal direkt mit code antworten:


for /f "usebackq delims=" %%i in ("%Liste%") do robocopy %Quelle% %Ziel% *.* /COPY:D /MIR /W:0 /R:0 /LOG+:%LOG% & echo %errorlevel%
jonny83
jonny83 25.08.2010 um 16:31:00 Uhr
Goto Top
nochmal - habs jetzt so gemacht aber klappt nicht:


set "LOG2=C:\skripte\logs\Skripte_Backup2.log"


for /f "usebackq delims=" %%i in ("%Liste%") do robocopy %Quelle% %Ziel% *.* /COPY:D /MIR /W:0 /R:0 /LOG+:%LOG% & Echo %%i %ERRORLEVEL% >> %LOG2%


Server1 0
Server2 0
Server3 0
Server4 0
Server5 0
Server6 0
Server7 0
Server8 0
Server9 0
Server10 0
Karo
Karo 25.08.2010 um 16:35:27 Uhr
Goto Top
face-smile kleine doofe Fräge: Wenn jetzt aber kein Fehler bei Deinen Jobs auftritt, dann sollte doch wohl 0 kommen, oder? Ich wäre damit zufrieden.

Karo
jonny83
jonny83 25.08.2010 um 16:43:07 Uhr
Goto Top
ich wäre dann auch zufrieden face-big-smile

aber ich habe ja extra einen Zielordner so verändert das der Benutzer, welcher die CMD ausführt, keine Schreibrechte hat.

Im "LOG" sehe ich ja auch das robocopy "Zugriff verweigert" schreibt.

Also, vertrau mir, das environment ist korrekt konfiguriert.

wenn ich den Befehl direkt in der CMD (als der explizite Benutzer) ausführe erhalte ich auch meinen robocopy errorlog Wert ´8´ ! 8 steht hier dafür, dass robocopy "Zugriff verweigert" bekommen hat ...

so - nun zurück.

ich glaube ja, so als Bäckerfachangestellter face-big-smile, das die For-Schleife immer der letzte ist der den errorlog wertet. Die For-Schleife funktioniert ja auch prächtig ^^

Deine Idee fand ich schon sehr gut - bring die Errorlog IN DIE Schleife rein - so dass wir es auch IN DER Schleife in einer TXT schreiben - dann kann die For-Schleife ja gern das errorlog überschreiben - wir hätten es ja dann schon weggeschrieben .... leider bleibt das Theorie weil ich es nicht schaffe überhaupt den echten Errorlog von robocopy zu sehen .... egal - nein völlig egal wo ich "(&) echo "errorlog"" hin schreibe ....

nochmal : S-O-S
Biber
Biber 25.08.2010 um 17:08:38 Uhr
Goto Top
Moin jonny83,

für den CMD-Interpreter, also die CMD.exe, die deinen Batch durchnudelt, ist doch aber dieses hier:

....
for /f "usebackq delims=" %%i in ("%Liste%") do robocopy [...blah ..]..&  Echo %%i %ERRORLEVEL% >> %LOG2%
...
...genau eine Befehlszeile.
Und in einer Befehlszeile werde alle Variablen genau einmal aufgelöst, ungefähr dann, wenn der Buchstabe "f" der "for /f"-Anweisung gelesen wird.

Zu diesem Zeitpunkt wird %LOG% zu "C:\skripte\logs\Skripte_Backup.log" aufgelöst und eben auch %errorlevel% zu dem, was es vor dem ersten "f" der Zeile hat... zu 0, falls vorher kein Fehler war.

Wenn du eine Variable quasi erst dann auflösen willst, wenn die Ausführung unmittelbar beim ersten "%"-Zeichen von %errorlevel% angelangt ist, dann musst du die "verzögerte Variablenaulösung", neudeutsch "delayed expansion" verwenden und das deiner CMD-Interprerin sagen.

Dazu 2 Schritte:
a) am Anfang des Batches statt "Setlocal" ein "Setlocal EnableDelayedExpansion" (denn die CMD.exe spricht neudeutsch)
b) diejenigen Variablen, die du "unmittelbar vorm Verwenden" versätet auflösen willst, e.g. %errorlevel%,, statt mit Prozentzeichen mit Ausrufungszeichen einrahmen.

Sinngemäß:
....
Setlocal EnableDelayedExpansion
..
....

for /f "usebackq delims=" %%i in ("%Liste%") do robocopy [...blah ..]..&  Echo %%i !ERRORLEVEL! >> %LOG2%
...

Beispiele soltest du auch ohne Mühe einige hier im Forum mit die Suchfunktion finden.

Grüße
Biber
jonny83
jonny83 26.08.2010 um 08:51:59 Uhr
Goto Top
Hallo Biber,

du bist unglaublich genial!

Ich danke dir - natürlich funktioniert das jetzt alles wunderbar.

Bzgl. der Suche - ich habe gesucht aber ich wusste nicht explizit nach was ich eigentlich suchen soll .... wegen dem EnableDelayedExpansion hätte ich nie was suchen können - ich kenn mich da nicht so aus - aber DU bist mir ein großer Lehrer in dem Punkt! Auch die For-Schleife habe ich ja von dir!

Also - vielen vielen Dank!!!!