退出 /b 0 不会将 %errorlevel% 设置为 0

Arn*_*rtz 4 windows batch command-line windows-error-reporting jenkins

我有一个奇怪的行为,将批处理脚本中的 errorlevel 设置为 0。

a.bat在 Jenkins 作业上调用批处理脚本,它依次调用第二个脚本b.cmd并在调用后评估错误级别:

:: b.cmd
:: some stuff, but relevant is only this:
@echo b errorlevel: %errorlevel%
EXIT /B 0
Run Code Online (Sandbox Code Playgroud)

“主要”脚本:

:: a.bat
pushd %CD%
cd..

@echo a errorlevel: %errorlevel%

set outputdir=".\some\exisiting\dir"
:: (1)
md %outpurdir%
@echo a errorlevel: %errorlevel%

:: (!)
if "$somevar" = "FOO" ( 
  cd .\WhereBIs

  :: (2)
  call :seterr 0
  @echo a errorlevel: %errorlevel%

  :: (3)
  call b.cmd

  @if %errorlevel% neq 0 (
    @echo a errorlevel: %errorlevel%
    set errmsg=Error calling b
    goto error
  )

  :: more stuff
)

:error
@echo %errmsg%
popd
:: (4)
@echo a errorlevel: %errorlevel%
@if %errorlevel% neq 0 exit %errorlevel%
Exit /B 1

:seterr
exit /b %1
Run Code Online (Sandbox Code Playgroud)

(我:seterr这个问题借了东西)

当我运行 Jenkins 作业时似乎会发生什么:

  1. md 返回并将 errorlevel 设置为 1,因为该目录已存在。
  2. 调用:seterr没有达到预期效果,errorlevel 保持为 1
  3. 调用b.cmd完成没有问题,错误级别中b是0,但呼叫ERRORLEVEL后a仍然1,我肯定不读答案的链接的问题后,期待。
  4. 在跳转到:error并调用之后popd,errorlevel 突然重置为 0 - 我也不希望如此。

有人知道这里可能发生什么吗?我没有不小心手动设置errorlevel,所以它应该是系统变量,而不是用户定义的。

dbe*_*ham 7

您尚未显示整个脚本。我知道的唯一可能的解释是您的代码位于更大的括号内的代码块中,可能是 FOR 循环或 IF 条件的一部分。

%ERRORLEVEL% 在解析行时展开,同时解析整个带括号的块。因此,您看到的 ERRORLEVEL 必须在最外面的括号开始之前就已存在。

如果您想在代码块中看到变化的值,您应该使用延迟扩展。

这是一个简单的演示:

@echo off
setlocal enableDelayedExpansion
set var=BEFORE
(
  set var=AFTER
  echo Normal expansion shows value before block started: %var%
  echo Delayed expansion shows the current value: !var!
)
Run Code Online (Sandbox Code Playgroud)

- 输出 -

Normal expansion shows value before block started: BEFORE
Delayed expansion shows the current value: AFTER
Run Code Online (Sandbox Code Playgroud)