2009-05-18 4 views
22

Batch-Dateien geben standardmäßig den Fehlercode des letzten Befehls zurück.Wie bekomme ich die Fehlerstufe von Befehlen in einer Pipe in Windows Batch-Programmierung?

Ist es irgendwie möglich, den Fehlercode eines früheren Befehls zurückzugeben. Vor allem ist es möglich, den Fehlercode eines Befehls in einer Pipe zurückzugeben?

Zum Beispiel diese einzeilige Batch-Skript

foo.exe 

gibt den Fehlercode von foo. Aber diese:

foo.exe | tee output.txt 

immer gibt den Exit-Code von tee, die Null ist.

+1

bezogen: http://stackoverflow.com/questions/11170753/windows-command-interpreter-how-to-obtain-exit-code-of-first-piped-command – eckes

+3

Mögliche Duplikate von [Windows-Befehlsinterpreter: wie Exit-Code des ersten Piped-Befehls erhalten] (https://stackoverflow.com/questions/11170753/windows-command-interpreter-how-to-obtain-exit-code-of-first-piped-command) –

+0

Was genau ist Das Ziel hier? Ist es einfach, auf den Fehlercode zu reagieren, die Ausgabe zu protokollieren und sie auf der Konsole anzuzeigen? Wenn dem so ist, hat mkl wahrscheinlich die beste Antwort, aber das habe ich erst bemerkt, nachdem ich meinen Eintrag gepostet und alles noch einmal überprüft habe. – jwdonahue

Antwort

3

Eine Problemumgehung besteht darin, eine Indirektion durch eine Datei vorzunehmen.

Like this

foo.exe > tmp.txt 
set FOOERR=%ERRORLEVEL% 
cat tmp.txt 
exit %FOOERR% 
+14

Dies vereitelt den ganzen Punkt der Verwendung von Tee, die sofortige Konsolenausgabe sowie in der Datei protokolliert werden soll. –

2

Nach etwa einem Tag gräbt, fand ich einen Weg, das zu tun:

set error_=0 
9>&1 1>&2 2>&9 (for /f "delims=" %%i in ('9^>^&1 1^>^&2 2^>^&9 ^(^(^(2^>^&1 call "%homeDir%%1"^) ^|^| ^(1^>^&2 2^>nul echo FAILED^)^) ^| 2^>nul "%homeDir%mtee" /T /+ "%homeDir%logs\%date_%_%1.log"^)') do (set error_=1)) 

exit /b %error_% 

In dem obigen Beispiel "% homedir %% 1" ausgeführt wird und Seine Ausgabe wird an "% homeDir% mtee" weitergeleitet. Diese Zeile erkennt Fehler (ich würde vorschlagen, dass Sie ein Diagramm der Stapelkontexte und ihrer stdin/stdout/stderr Zuordnungen zeichnen, um zu verstehen, was es tut :-)). Ich habe keinen guten Weg gefunden, den tatsächlichen Fehlerlevel zu extrahieren. Das Beste, was ich bekam, war das ‚echo‘ Befehl mit einigen Batch-Skript Aufruf ‚Call rc.bat‘, die aussehen zu ersetzen:

@echo %errorlevel% 

und dann ersetzen ‚gesetzt error_ = 1‘ mit ‚gesetzt Fehler _ =% %ich'.

Aber das Problem ist, dass dieser Anruf auch fehlschlagen kann, und es ist nicht einfach, das zu erkennen. Trotzdem ist es viel besser als nichts - ich habe dafür im Internet keine Lösung gefunden.

1

Sie das Problem, indem Sie eine Wrapper um Ihre Befehlsdatei lösen:

rem wrapper for command file, wrapper.cmd 

call foo.exe 

echo %errorlevel% 

if errorlevel 1 goto... 

Dann T-Stück an den Wrapper anhängen:

wrapper.cmd | tee result.log 

Natürlich ist dies nicht genau das gleiche, z.B. Wenn Sie mehrere Dateien in der umschlossenen Datei anmelden möchten, ist das nicht möglich, aber in meinem Fall hat es das Problem gelöst.

4

Die Variable% ERRORLEVEL% wird nicht aktualisiert, bevor der Befehl piped ausgeführt wird. Sie müssen einen Wrapper verwenden, wie in den anderen Antworten empfohlen.

Sie können jedoch verwenden "IF ERRORLEVEL #". Zum Beispiel:

(
type filename 
@REM Use an existing (or not) filename to test each branch 
IF ERRORLEVEL 1 (echo ERROR) ELSE (echo OKAY) 
) > logfile.txt 

Der ECHO wird nur ausgeführt, wenn ein Fehler zurückgegeben wurde; % ERRORLEVEL% scheint jedoch inkonsistent zu sein.

Bearbeiten: Beispiel geändert, um lauffähig zu sein, wie es ist.

+5

Dies funktioniert nicht für mich Ich bekomme "ECHO war zu dieser Zeit unerwartet." –

+2

Können die 5 Personen, die diese Antwort upvotiert haben, bitte Repro-Schritte zur Verfügung stellen? Ich bekomme was @SamMackrill bekommt. Windows erwartet zu diesem Zeitpunkt nichts. – harpo

5

Ich hatte ein ähnliches Problem und entschied mich für die folgende Lösung, da ich nicht den genauen Fehlercode nur Erfolg oder Misserfolg feststellen musste.

echo > .failed.tmp  

(foo.exe && del .failed.tmp) | tee foo.log 

if exist .failed.tmp (
    del .failed.tmp 
    exit /b 1 
) else (
    exit /b 0 
) 
0

Um T-Stück für den Eintritt bat-Datei, nicht für einzelne Befehl aufrufen und verwenden Errorlevel frei, ich Trick wie folgt verwenden:

if "%1" == "body" goto :body 
call %0 body | tee log.txt 
goto :eof 
:body 

set nls_lang=american_america 
set HomePath=%~dp0 

sqlplus "usr/[email protected]" "@%HomePath%script.sql" 
if errorlevel 1 goto dberror 

rem Here I can do something which is dependent on correct finish of script.sql  

:dberror 

echo script.sqlerror failed 

es T-Shirt mit trennt alle Befehle innerhalb Charge aus aufrufen.

Verwandte Themen