Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the error level of commands in a pipe in Windows batch programming?

People also ask

What is error level in batch file?

Error Level. The environmental variable %ERRORLEVEL% contains the return code of the last executed program or script.

What is error level CMD?

The ERRORLEVEL is a value returned by most cmd.exe commands when they end that change depending on a series of conditions, so knowing the value that the commands return is valuable information that may aid to write better Batch files.

What does %% mean in batch script?

Represents a replaceable parameter. Use a single percent sign ( % ) to carry out the for command at the command prompt. Use double percent signs ( %% ) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %a, %b, or %c. ( <set> )

What is == in batch?

[ == ] (Double Equals) The "IF" command uses this to test if two strings are equal: IF "%1" == "" GOTO HELP. means that if the first parameter on the command line after the batch file name is equal to nothing, that is, if a first parameter is not given, the batch file is to go to the HELP label.


I had a similar problem and settled on the following solution as I did not need to detect the exact error code just success or failure.

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
)

One workaround is to make an indirection through a file.

Like this

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

After about one day of digging, I found a way to do that:

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 the example above "%homeDir%%1" is being executed and its output is piped to "%homeDir%mtee". This line detects failures (I'd suggest you to draw a diagram of batch contexts and their stdin/stdout/stderr assignments in order to understand what it does :-) ). I did not find a good way to extract the actual errorlevel. The best thing I got was to replace the 'echo' command with some batch script call 'call rc.bat' which look like:

@echo %errorlevel%

and then replace 'set error_=1' with 'set error_=%%i'.

But the problem is that this call may fail too, and it is not easy to detect that. Still, it is much better than nothing -- I did not find any solution for that on the Internet.


The %ERRORLEVEL% variable doesn't get updated before the piped command is run; you have to use a wrapper as advised in the other answers.

However, you can use "IF ERRORLEVEL #". For example:

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

The ECHO will only run if an error was returned; however %ERRORLEVEL% seems inconsistent.

Edit: Changed example to be runnable as-is.


To call tee for entry bat-file, not for single command, and use errorlevel freely, I use trick like this:

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

set nls_lang=american_america
set HomePath=%~dp0

sqlplus "usr/pwd@tnsname" "@%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

it separates using tee from calling any commands inside batch.