Перенаправление вывода из консольного приложения Oracle в именованный канал

Перенаправление вывода из консольного приложения Oracle в именованный канал

В настоящее время я разрабатываю плагин для компиляции кода 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

Связанный контент