.bat 文件中的错误处理

Posted

技术标签:

【中文标题】.bat 文件中的错误处理【英文标题】:Error Handling in .bat File 【发布时间】:2017-03-15 11:17:12 【问题描述】:

我有一个 .bat 文件,它运行两个 SQL 文件并移动文件。我需要在这个 .bat 文件中进行一些错误处理。我希望它获取 sql 中生成的错误并将其传递给 AutoSys 我得到了这个代码:

#!/bin/sh 
. $HOME/.bash_profile

sqlplus -s $AUTOSYS_DB_USER/$AUTOSYS_DB_PASSWD <<!
WHENEVER OSERROR EXIT 999;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
alter session set nls_date_format='DD/MM/YYYY';
execute P_LOST_APPROVALS;
!

exit_code=$?
if [ $exit_code != 0 ]; then
echo "Error calling sqlplus, return code = " $exit_code
exit $exit_code
fi

exit 0

但是,我需要它在 .bat 文件而不是 Linux 中运行?

我目前有:

echo exit | sqlplus -s %CONNECT% @Code.sql 
IF %ERRORLEVEL% NEQ 0 (
echo Unsuccessful
goto @ERROR_HANDLING_SQL
)

完整的 .bat 文件:

@echo off
call config.bat
SET CONNECT=%var1%/%var2%@avpr.world

Pushd  Location


Set SCRIPTPATH=Location
Set RESULTPATH=Location


echo exit | sqlplus -s %CONNECT% @Code.sql
IF %ERRORLEVEL% NEQ 0 (
echo Unsuccessful
goto @ERROR_HANDLING_SQL
)


echo exit | sqlplus -s %CONNECT% @createTXT.sql > File%date:~0,2%%date:~3,2%%date:~6,4%.txt
IF %ERRORLEVEL% NEQ 0 (
echo Unsuccessful
goto @ERROR_HANDLING_SQL
 )



move "File%date:~0,2%%date:~3,2%%date:~6,4%.txt" %RESULTPATH%


echo exit | sqlplus -s %CONNECT% @dropTable.sql
IF %ERRORLEVEL% NEQ 0 (
echo Unsuccessful
goto @ERROR_HANDLING_SQL
)



 : ERROR_HANDLING_SQL
 <echo -1>

pause
Exit

【问题讨论】:

I have a .bat file我在您的问题中没有看到任何批处理代码 请更改您的问题标题和描述并删除批处理文件标签。这与 Windows 批处理文件无关。 提供完整的bat文件 去掉goto @Label命令行中的@前缀,然后写:Label这样的标签(:和标签名称之间没有空格)... @E_McAndrew 我已经编辑了我的答案。我还看到您在帖子中添加了一个批处理脚本。如果您“当前拥有”的内容来自我的解决方案,请报告。目前看来我没有回答你的问题,只是复制了你的代码。 【参考方案1】:

批处理中退出代码$? 的等效项是errorlevel,可通过变量%ERRORLEVEL% 访问。在批处理脚本中,存在一种使用错误级别的特殊形式的 IF 子句:IF ERRORLEVEL n 等价于:“如果错误级别大于或等于 n。与在 bash 中一样,值 0 表示上一个命令执行时没有错误(并非总是如此,某些命令不设置错误级别)。所以你有两个选择:

    IF %ERRORLEVEL% NEQ 0 是 bash 脚本中 if 语句的直译。请注意,您必须在以(...) 分隔的代码块内使用delayed expansion 版本IF !ERRORLEVEL! NEQ 0(查看this question 解释原因) IF ERRORLEVEL 1 恕我直言更合适(不过取决于您的喜好)。也适用于 (...) 代码块,但假定命令从未设置负错误级别(从未遇到过但值得一提)

通常使用set 命令设置变量不会更改错误级别,因此您可以选择两个选项之一。但由于我现在没有 Windows 机器来测试它,我会安全地玩它并给你第一个选择。一旦我测试了第二个选项,我将编辑我的答案。

set exit_code=%ERRORLEVEL%
if %exit_code% NEQ 0 (  
    echo Error calling sqlplus, return code = %exit_code%
    exit /b %exit_code%
)

最后的建议:使用exit /b 而不是exitexit也会批量退出命令行

编辑我已经测试了第二个版本,它也能正常工作。所以上面的代码可以替换为:

set exit_code=%ERRORLEVEL%
IF ERRORLEVEL 1 (  
    echo Error calling sqlplus, return code = %exit_code%
    exit /b %exit_code%
)

This blog article 很好地解释了为什么应该使用这个版本而不是使用 %ERRORLEVEL% 变量的第一个版本。

在his comment 中提醒我的另一个选项@aschipfl 是使用conditional executions operators &amp;&amp; and ||

仅当 command1 成功时,command1 &amp;&amp; command2 才会执行 command2 仅当 command1 失败时,command1 || command2 才会执行 command2

两个运算符都使用退出代码(在大多数情况下与 errorlevel 相同,但并非总是如此)来确定命令是失败还是成功。

我还看到您发布了批处理文件。不过有一点我想指出:goto @ERROR_HANDLING_SQL 会抛出错误,因为没有标签@ERROR_HANDLING_SQL。不过,在您的脚本末尾有一个标签 ERROR_HANDLING_SQL。如果您尝试跳转到该标签,则应将所有出现的 goto @ERROR_HANDLING_SQL 替换为 goto ERROR_HANDLING_SQL

【讨论】:

谢谢,我需要参考我的 SQL 脚本吗?因此,例如我有一个名为 Code.sql 的脚本是否需要在此处引用? @E_McAndrew 我发布的答案仅与错误处理有关(如您的标题所述)。您使用 here-document 执行的 sql 脚本必须以批处理方式执行,否则批处理不支持 here-documents 我的批处理文件运行 sql,但我希望对此有错误报告。那么这不是像您在同一个脚本中回答的那样使用 if 语句的情况吗? @E_McAndrew 您必须将代码放在我的答案中,就在您的 sql 命令之后,因为您希望得到 sql 的错误报告。 好的,所以我在我的 SQL 运行之后直接包含它,它实际上不需要在代码中对它进行任何引用?

以上是关于.bat 文件中的错误处理的主要内容,如果未能解决你的问题,请参考以下文章

在.bat(批处理文件)中查找和替换导致未知错误的字符串

错误记录Windows 系统 bat 脚本报错 ( Java 生成 bat 脚本乱码处理 | 输出 GB2312 字符串 | Windows 中的换行时 )

如果出现错误,如何获取批处理文件 .bat 继续执行下一条语句

错误记录Windows 系统 bat 脚本报错 ( 使用 pause 拦截窗口自动关闭 | 方便查看错误 )

Maven 构建中的错误:无法识别 mvn.bat

Windows 批处理文件:.bat 与 .cmd?