Управление обработкой ошибок при запуске sqlplus из сценариев оболочки

#!/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

Я ввожу значения мусора, пытаясь заставить этот скрипт потерпеть неудачу. Но, что раздражает, он продолжает двигаться вперед без какого-либо упоминания кода ошибки. Что еще нужно сделать здесь?


person roymustang86    schedule 06.02.2013    source источник
comment
Под какой учетной записью ОС вы работаете? К какой базе данных подключается скрипт?   -  person APC    schedule 11.02.2013
comment
Я попробовал ваш скрипт, и файл журнала фиксирует код ошибки. Вот выдержка из лог-файла: ERROR: ORA-01017: invalid username/password; logon denied SP2-0734: unknown command beginning "DBMS_OUTPU..." - rest of line ignored.   -  person Incognito    schedule 12.02.2013
comment
Могу я узнать, что вы получаете в файле журнала при выполнении скрипта?   -  person Incognito    schedule 12.02.2013


Ответы (5)


То, что Макс говорит, верно. Попробуйте этот модифицированный скрипт

#!/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 для получения дополнительной информации.

person Aji Mathew    schedule 12.02.2013
comment
Я получаю только код ошибки 122 вместо фактического сообщения об ошибке БД. Знаете ли вы способ захвата вывода? - person roymustang86; 12.02.2013
comment
Сообщение об ошибке перенаправляется в файл shell_log.txt. Посмотрите на этот файл в вашем текущем каталоге. Если вы хотите захватить вывод в сценарии оболочки, вам нужно удалить перенаправление и назначить вывод 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 ) - person Aji Mathew; 13.02.2013
comment
Сценарий оболочки в ОС UNIX может возвращать коды до 255. Поэтому я не понимаю, как WHENEVER SQLERROR EXIT SQL.SQLCODE; может правильно возвращать коды SQL выше 255? Например. ORA-12703 это преобразование набора символов не поддерживается. На самом деле я только что провел тест и запустил неверный SQL, который не работает с ORA-00936: отсутствующее выражение, плохой sqlplus вернул 168 (!) Таким образом, фактический код возврата 936 был завернут в, а получен только остаток вернулся. 936%256=168. Это неправильный ответ. - person Tagar; 08.08.2014

возможно, что ваши операторы всякий раз выполняются после установления соединения с БД (поскольку вы упомянули их впоследствии). Попробуйте следующий код: -

$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
person Max    schedule 10.02.2013
comment
Я буквально не могу разобрать это предложение. - person Maaark; 28.11.2019

Ответ Аджи с

WHENEVER SQLERROR EXIT SQL.SQLCODE;

а затем с помощью

sql_return_code=$?

неверно (или неверно в большинстве случаев). Подробнее см. ниже.


Сценарий оболочки в ОС UNIX может возвращать коды до 255. Например. "ORA-12703 это преобразование набора символов не поддерживается" код возврата должен быть 12703, но он не подходит для 8-битного кода возврата UNIX.
На самом деле я только что провел тест и запустил неверный 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

Таким образом, он выполнит поиск файла журнала спула, а затем вырежет фактический последний код ORA.

person Tagar    schedule 08.08.2014

Тот факт, что вы вводите поддельные значения, вероятно, связан только с логином. Затем: Проверьте подключение к базе данных с помощью сценария оболочки.

WHENEVER ... для ошибок во время выполнения скрипта SQL. Как только вы успешно соединитесь со своим скриптом (я предполагаю, что это ваша проблема прямо сейчас), вы должны получить вид ошибки, управляемой WHENEVER ERROR, потому что вы забыли EXEC в своей строке с DBMS_OUTPUT.

person Plouf    schedule 11.02.2013

Вы можете отловить только ошибку sql или ошибку os. dbms_output завершится ошибкой на самом уровне sqlplus, поэтому установка ошибки всякий раз не повлияет на него.

person rajesh    schedule 08.04.2013