从 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
管理的那种错误,因为你忘记了EXEC
与DBMS_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 << 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 命令的输出状态?