2009-05-18 9 views
22

I file batch restituiscono il codice di errore dell'ultimo comando per impostazione predefinita.Come si ottiene il livello di errore dei comandi in una pipe nella programmazione batch di Windows?

È in qualche modo possibile restituire il codice di errore di un comando precedente. In particolare, è possibile restituire il codice di errore di un comando in una pipe?

Ad esempio, questa una riga script batch

foo.exe 

restituisce il codice di errore di foo. Ma questo:

foo.exe | tee output.txt 

restituisce sempre il codice di uscita di tee, che è pari a zero.

+1

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

+3

Eventuali duplicati di [interprete dei comandi di Windows: come per ottenere il codice di uscita del primo comando in filodiffusione] (https://stackoverflow.com/questions/11170753/windows-command-interpreter-how-to-obtain-exit-code-of-first-piped-command) –

+0

che cosa è esattamente l'obiettivo qui? È sufficiente essere in grado di rispondere al codice di errore, registrare l'output e visualizzarlo sulla console? Se è così, probabilmente mkl ha la risposta migliore, ma non me ne sono reso conto fino a dopo aver postato il mio e rivisto tutto ancora una volta. – jwdonahue

risposta

3

Una soluzione è quella di eseguire un riferimento indiretto tramite un file.

Ti piace questa

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

In questo modo si sconfigge l'intero punto di utilizzo del tee che serve per ottenere l'output della console immediato e per essere registrato nel file. –

2

Dopo circa un giorno di scavo, ho trovato un modo per farlo:

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_% 

Nell'esempio precedente "% homedir %% 1" è in corso di esecuzione e il suo output è convogliato su "% homeDir% mtee". Questa linea rileva i fallimenti (ti suggerisco di disegnare un diagramma di contesti batch e i loro incarichi stdin/stdout/stderr per capire cosa fa :-)). Non ho trovato un buon modo per estrarre il vero errorlevel. La cosa migliore che ho avuto è stato quello di sostituire il comando 'echo' con alcuni lotti di chiamata script 'chiamata rc.bat' che assomigliano:

@echo %errorlevel% 

e quindi sostituire 'set Errore_ = 1' con 'l'errore set _ =% %io'.

Ma il problema è che anche questa chiamata potrebbe non riuscire e non è facile rilevarla. Tuttavia, è molto meglio di niente - non ho trovato alcuna soluzione per questo su Internet.

1

È possibile risolvere il problema con la creazione di un wrapper per il file di comandi:

rem wrapper for command file, wrapper.cmd 

call foo.exe 

echo %errorlevel% 

if errorlevel 1 goto... 

quindi aggiungere tee al wrapper:

wrapper.cmd | tee result.log 

Naturalmente questo non è esattamente lo stesso, per esempio se si desidera accedere a diversi file nel file spostato, non è possibile, ma nel mio caso ha risolto il problema.

4

La variabile% ERRORLEVEL% non viene aggiornata prima dell'esecuzione del comando di piping; devi usare un wrapper come consigliato nelle altre risposte.

Tuttavia, è possibile utilizzare "IF ERRORLEVEL #". Per esempio:

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

L'ECHO verrà eseguito solo se un errore è stato restituito; tuttavia% ERRORLEVEL% sembra incoerente.

Modifica: Esempio modificato per essere eseguibile così com'è.

+5

Questo non funziona per me. "ECHO era inaspettato in questo momento". –

+2

Le 5 persone che hanno messo in svantaggio questa risposta possono fornire passaggi di ripetizione? Ottengo ciò che @SamMackrill ottiene. Windows non si aspetta nulla in questo momento. – harpo

5

Avevo un problema simile e ho risolto la seguente soluzione in quanto non avevo bisogno di rilevare il codice di errore esatto solo in caso di esito positivo o negativo.

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

Per chiamare tee per l'ingresso bat-file, non per il singolo comando, e utilizzare errorlevel liberamente, io uso trucco come questo:

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 

si separa con tee di chiamare qualsiasi comando all'interno dei lotti.

Problemi correlati