默认情况下,批处理文件返回最后一个命令的错误码。
有没有办法返回以前命令的错误码?特别是,在管道中返回命令的错误码是否可能?
例如,这个一行的批处理脚本:
foo.exe
返回foo的错误代码。但这个:
foo.exe | tee output.txt
始终返回tee的退出码,该退出码为零。
默认情况下,批处理文件返回最后一个命令的错误码。
有没有办法返回以前命令的错误码?特别是,在管道中返回命令的错误码是否可能?
例如,这个一行的批处理脚本:
foo.exe
返回foo的错误代码。但这个:
foo.exe | tee output.txt
始终返回tee的退出码,该退出码为零。
我也遇到了类似的问题,最终采用以下解决方案,因为我不需要检测确切的错误代码,只需要知道成功或失败。
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
)
%ERRORLEVEL%变量在管道命令运行之前不会被更新;你需要像其他答案中建议的那样使用包装器。
然而,你可以使用“IF ERRORLEVEL #”。例如:
(
type filename
@REM Use an existing (or not) filename to test each branch
IF ERRORLEVEL 1 (echo ERROR) ELSE (echo OKAY)
) > logfile.txt
一种解决方法是通过文件进行间接引用。
就像这样
foo.exe > tmp.txt
set FOOERR=%ERRORLEVEL%
cat tmp.txt
exit %FOOERR%
经过大约一天的搜索,我找到了一种方法:
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_%
@echo %errorlevel%
然后将“set error_=1”替换为“set error_=%%i”。
但问题在于,这个调用也可能失败,而且很难检测到。尽管如此,它仍然比没有好得多——我在互联网上没有找到任何解决方案。
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
它通过使用tee进行分离,使批处理中不调用任何命令。
您可以通过创建一个包装器来解决问题:
rem wrapper for command file, wrapper.cmd
call foo.exe
echo %errorlevel%
if errorlevel 1 goto...
然后将tee附加到包装器中:
wrapper.cmd | tee result.log