
В настоящее время я разрабатываю плагин для компиляции кода Oracle в моем текстовом редакторе. Разработчики SQL Developer недавно добавили версию командной строки sqlcl
. Проблема в том, что это приложение Java, и запуск его ( jvm
) каждый раз, когда мне нужно выполнить компиляцию, может быть затратным — по некоторым сообщениям, это занимает ~20 секунд.
Одно из предложений, которое я видел, состояло в использовании именованного канала, и если я делаю это вручную, то, похоже, это работает хорошо.
Терминал 1:
mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog
Терминал 2:
echo "conn hr/[email protected]/xe" > sqlconsole
И заявления выполняются успешно.
Проблема в том, что в терминале 2 я не получаю никаких выходных данных из терминала 1 (а мне это нужно).
..
я нашел этостатьяо чтении вывода из именованного канала, однако даже при этом вывод sqlcl
не перенаправляется (и, как я уже писал, кажется, имеет поврежденный ввод)
#!/bin/bash
#consolereader.sh
trap "rm -f sqlconsole" EXIT
if [[ ! -p sqlconsole ]]; then
echo "pipe does not exist" >&2
exit 1
fi
while true
do
if read line < sqlconsole; then
if [[ "$line" == 'quit' ]]; then
break
fi
echo $line
fi
done
Терминал 1:
mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog
Терминал 2:
./consolereader.sh &
echo "conn hr/[email protected]/xe" > sqlconsole
Есть ли лучший подход, который я могу использовать — например, оставить sqlcl
работу в фоновом режиме и при этом получать вывод в сеансе, из которого я отправляю команды?
..
Редактировать: Пробую решение Джермара:
setUpPipes.sh (терминал 1):
#!/bin/bash
rm -f sqlconsole
rm -f sqlconsole_out
mkfifo sqlconsole
mkfifo sqlconsole_out
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog | tee -a sqlconsole_out
compileOracle.sh (терминал 2):
#!/bin/bash
echo "begin.."
tail -f /home/trent/pipedemo/sqlconsole_out &
echo "about to run connection"
echo "conn hr/[email protected]/xe" > /home/trent/pipedemo/sqlconsole
echo "select * from dual" > /home/trent/pipedemo/sqlconsole
echo "disconnect" > /home/trent/pipedemo/sqlconsole
echo "finished"
exit 0
решение1
Один из подходов, который вы можете использовать, — это использовать команду SPOOL
в вашем интерпретаторе SQL.
Итак, начните свой именованный канал, как вы уже делали это:
mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog
Далее создайте свой скрипт SQL, но на этот раз включите serveroutput
и также подкачайте в указанный файл. В этом примере я просто сделаю это в out.txt
.
conn hr/[email protected]/xe
SPOOL out.txt
select * from dual;
set serveroutput on
exec dbms_output.put_line('PROCESS_FINISHED');
SPOOL OFF
disconnect
Здесь я также решил вывести строку в буферизованный файл - PROCESS_FINISHED
- как способ отметить завершение выполнения скрипта, поскольку скрипт SQL и скрипт bash будут выполняться параллельно, и скрипт bash, скорее всего, завершится до завершения скрипта.
После этого я могу создать bash-скрипт ( atomRunner.sh
) для отправки его в именованный канал:
#!/bin/bash
> out.txt
cat connect.sql > sqlconsole
MAX_TIME=10
scriptStart=$(date -u +"%s")
secondsSince=0
while true; do
if [[ "${secondsSince}" -ge "${MAX_TIME}" ]] || grep -q "PROCESS_FINISHED" out.txt; then
break
fi
nowDate=$(date -u +"%s")
secondsSince=$((nowDate-scriptStart))
sleep 0.1
done
cat out.txt
if [[ "${secondsSince}" -ge "${MAX_TIME}" ]]; then
echo "Script took longer than expected to complete" >&2
exit 1
fi
exit 0
Затем выполняется:
$ ./atomRunner.sh
SQL> set serveroutput on
SQL> select * from dual;
D
-
X
SQL> exec dbms_output.put_line('PROCESS_FINISHED')
PROCESS_FINISHED
SQL> SPOOL OFF