Странный пакетный скрипт CMD, сообщающий о% errorlevel%

В приведенном ниже сценарии при возникновении ошибки sql %errorlevel% равно 0 - почему?

IF %RELEASE% GTR 2 (
    (
    echo WHENEVER SQLERROR EXIT FAILURE
    echo @release.sql
    echo exit
    ) | sqlplus x/x@orcl
    echo error: %errorlevel%
    if %errorlevel% gtr 0 goto dberror
)   

Если я удалю блок if (см. Ниже), то% errorlevel% НЕ равен нулю! Почему оператор if влияет на уровень ошибки?

    (
    echo WHENEVER SQLERROR EXIT FAILURE
    echo @release.sql
    echo exit
    ) | sqlplus x/x@orcl
    echo error: %errorlevel%
    if %errorlevel% gtr 0 goto dberror

Обновление: поверьте, это был способ, которым я тестировал ошибку. Думаю вместо:

if %errorlevel% gtr 0 goto dberror

.. следует использовать:

if errorlevel 1 goto dberror

Полезная ссылка здесь


person Marcus Leon    schedule 09.02.2011    source источник
comment
Да, в самом деле. if errorlevel 1 на самом деле означает if errorlevel is 1 or greater. Уровень ошибок не является переменной среды. Он представляет собой код выхода последнего выполненного процесса и имеет собственный небольшой синтаксис if. : D   -  person GolezTrol    schedule 09.02.2011
comment
@GolezTrol: у него есть собственный синтаксис для проверок, но он также является переменной среды и может использоваться так же, как и любая другая переменная: отображение эхо, проверка значения, передача в качестве параметра ...   -  person Andriy M    schedule 10.02.2011


Ответы (1)


Вздох. Все дело в ужасном парсинге dos и точке, в которой cmd заменяет %errorlevel% своим значением. Когда вы заключаете команды в _2 _..._ 3_, cmd сначала считывает эти команды, как если бы все они были записаны в одной строке, расширяя переменные по мере продвижения. Таким образом, в вашем первом блоке кода %errorlevel% заменяется своим значением при анализе блока. Вы как будто написали:

IF 3 GTR 2 (
   (
   echo WHENEVER SQLERROR EXIT FAILURE
   echo @release.sql
   echo exit
   ) | sqlplus x/x@orcl
   echo error: 0
   if 0 gtr 0 goto dberror
)

(при условии, что $RELEASE было 3). Причина, по которой ваше if errorlevel исправление работает, заключается в том, что cmd не выполняет никакого (слишком) раннего расширения переменных в этой переформулировке. Вы можете использовать call, чтобы избежать этой проблемы:

IF %RELEASE% GTR 2 (
    (
    echo WHENEVER SQLERROR EXIT FAILURE
    echo @release.sql
    echo exit
    ) | sqlplus x/x@orcl
    call echo error: %%errorlevel%%
    call if %%errorlevel%% gtr 0 goto dberror
)

(что, я думаю, яснее, чем startlocal ENABLEDELAYEDEXPANSION и !errorlevel! - YMMV, конечно).

person bobbogo    schedule 09.02.2011
comment
P.S. Можно установить уровень ошибки на отрицательное число (!), Поэтому NEQ 0 является наиболее полным тестом. (Я чувствую, что надвигается еще один вздох.) - person bobbogo; 10.02.2011