从 shell 脚本运行 sqlplus 时管理错误处理

Posted

技术标签:

【中文标题】从 shell 脚本运行 sqlplus 时管理错误处理【英文标题】:Managing error handling while running sqlplus from shell scripts 【发布时间】:2013-01-21 22:47:56 【问题描述】:
#!/bin/sh

echo "Please enter evaluate database username"
read eval_user
echo "Please enter evaluate database password"
read eval_pass
echo "Please enter the database name"
read db_name

LOGFILE=shell_log.txt

$ORACLE_HOME/bin/sqlplus -s /nolog <<-EOF>> $LOGFILE
connect $eval_user/$eval_pass@$db_name
WHENEVER OSERROR EXIT 9;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
DBMS_OUTPUT.put_line('Connected to db');
EOF

if [ $? != 0 ]
then 
echo "The upgrade script failed. Please refer to the log results.txt for more information"
echo "Error code $?"
exit 0;
fi

我正在输入垃圾值,试图强制此脚本失败。但是,令人讨厌的是,它一直在继续前进,而没有提及任何错误代码。这里还需要做什么?

【问题讨论】:

您在哪个操作系统用户帐户下运行?脚本登录到什么数据库? 我试过你的脚本,日志文件正在捕获错误代码。这是从日志文件中获取的内容:ERROR: ORA-01017: invalid username/password; logon denied SP2-0734: unknown command beginning "DBMS_OUTPU..." - rest of line ignored. 请问,当您执行脚本时,您在日志文件中得到了什么? 【参考方案1】:

您的whenever 语句可能在与数据库的连接建立后执行(因为您后来提到了它们)。试试下面的代码:-

$ORACLE_HOME/bin/sqlplus -s /nolog <<-EOF>> $LOGFILE
WHENEVER OSERROR EXIT 9;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
connect $eval_user/$eval_pass@$db_name
DBMS_OUTPUT.put_line('Connected to db');
EOF

【讨论】:

我真的无法解析这句话。 @Maaark,现在试试。我编辑了答案。【参考方案2】:

您输入虚假值的事实可能仅与登录有关。然后: Check database connectivity using Shell script

WHENEVER ... 用于 SQL 脚本执行期间的错误。一旦你成功连接到你的脚本(我认为这是你现在的问题),你应该得到WHENEVER ERROR 管理的那种错误,因为你忘记了EXECDBMS_OUTPUT 的行。

【讨论】:

【参考方案3】:

麦克斯说的是对的。试试这个修改后的脚本

#!/bin/sh

echo "Please enter evaluate database username"
read eval_user
echo "Please enter evaluate database password"
read eval_pass
echo "Please enter the database name"
read db_name

LOGFILE=shell_log.txt

sqlplus -s /nolog <<-EOF>> $LOGFILE
WHENEVER OSERROR EXIT 9;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
connect $eval_user/$eval_pass@$db_name
DBMS_OUTPUT.put_line('Connected to db');
EOF

sql_return_code=$?

if [ $sql_return_code != 0 ]
then
echo "The upgrade script failed. Please refer to the log results.txt for more information"
echo "Error code $sql_return_code"
exit 0;
fi

请注意使用 sql_return_code 来捕获 SQLPLUS 返回码。

DBMS_OUTPUT 语句应该失败并出现错误 - “SP2-0734:未知命令开始...”。您可以在日志文件中找到错误消息。

可以使用错误记录工具捕获 SQLPLUS 11g 中的 sp2 错误。请查看http://tkyte.blogspot.co.uk/2010/04/new-thing-about-sqlplus.html 了解更多信息。

【讨论】:

我只得到错误代码 122,而不是实际的 db 错误消息。你知道捕获输出的方法吗? 错误信息被重定向到“shell_log.txt”。查看当前目录中的该文件。如果要在 shell 脚本中捕获输出,则需要删除重定向并将 SQLPLUS 的输出分配给变量。例如:- SQL_RESULT=$(sqlplus -s /nolog &lt;&lt; EOF WHENEVER SQLERROR EXIT FAILURE WHENEVER OSERROR EXIT FAILURE SET SERVEROUTPUT ON connect $eval_user/$eval_pass@$db_name exec DBMS_OUTPUT.put_line('Connected to db'); exit EOF ) UNIX 操作系统中的 Shell 脚本最多可以返回 255 个代码。所以我不明白 WHENEVER SQLERROR EXIT SQL.SQLCODE;可以正确返回 255 以上的 SQL 代码吗?例如。 ORA-12703 不支持此字符集转换 实际上我只是做了一个测试并运行了一个错误的 SQL,该 SQL 失败并出现 ORA-00936: missing expression bad sqlplus returned 168 (!) 所以实际的返回码 936 被包装了,剩下的只是回来。 936%256=168。这不是一个正确的答案。【参考方案4】:

您只能捕获 sql 错误或 os 错误。 dbms_output 将在 sqlplus 级别本身失败,因此无论何时错误设置都不会影响它。

【讨论】:

【参考方案5】:

阿吉的回答与

WHENEVER SQLERROR EXIT SQL.SQLCODE;

然后使用

sql_return_code=$?

不正确(或在大多数情况下不正确)。请参阅下面的详细信息。


UNIX 操作系统中的 Shell 脚本最多可以返回 255 个代码。 例如。 “ORA-12703 不支持此字符集转换”返回码应为 12703,但它不适合 UNIX 8 位返回码。 实际上,我只是做了一个测试并运行了一个错误的 SQL,该 SQL 失败并显示“ORA-00936:缺少表达式”- sqlplus 返回 168 (!)。 所以实际的返回码 936 被包装在 256 处,剩下的就被返回了。 936%256=168。

这可能在 Windows 上可以工作(未经测试),但在 UNIX 上则不行(如上文所述进行了测试)。

唯一可靠的机制可能是将结果假脱机到日志文件中,然后执行类似的操作

tail -n 25 spool.log | egrep "ORA-" | tail -n 1 | cut -d: -f1 | cut -d- -f2

所以它会 grep 假脱机日志文件,然后剪切实际最新的 ORA 代码。

【讨论】:

OP 可以只使用WHENEVER SQLERROR EXIT 10; 或其他东西。但好点。 SQLCODE 可能会 mod 256 等于 0!

以上是关于从 shell 脚本运行 sqlplus 时管理错误处理的主要内容,如果未能解决你的问题,请参考以下文章

如何在 shell 脚本中运行 SQL 查询时获得类似 SQLPLUS 的输出

如何从 shell/shell 脚本获取 sqlplus 命令的输出状态?

访问 sqlplus 的 Shell 脚本

linux下shell脚本中sqlplus调用shell变量的问题

从 SQLPlus 运行 SQL 脚本失败时如何查看错误?

将假脱机文件的名称从 shell 脚本传递给 sqlplus