Redirecionando a saída de um aplicativo de console Oracle em um pipe nomeado

Redirecionando a saída de um aplicativo de console Oracle em um pipe nomeado

Atualmente estou desenvolvendo um plugin para compilar código Oracle em meu editor de texto. O pessoal que desenvolveu o SQL Developer adicionou recentemente uma versão de linha de comando sqlcl. O problema é que este é um aplicativo Java - e ativá-lo ( jvm) sempre que preciso fazer uma compilação pode ser caro - com alguns relatos de que leva cerca de 20 segundos.

Uma sugestão que vi foi usar um pipe nomeado, que, se feito manualmente, parece funcionar bem.

Terminal 1:

mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog

Terminal 2:

echo "conn hr/[email protected]/xe" > sqlconsole

E as instruções são executadas com sucesso.

O problema com isso, porém, é que no terminal 2, não estou recebendo nenhuma saída do terminal 1 (o que desejo).

..

Eu achei istoartigosobre a leitura da saída de um pipe nomeado, no entanto, mesmo com isso, a saída de sqlclnão é redirecionada (e, ao escrever isso, parece ter uma entrada quebrada)

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

Terminal 1:

mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog

Terminal 2:

./consolereader.sh &
echo "conn hr/[email protected]/xe" > sqlconsole

Existe uma abordagem melhor que eu possa adotar - de modo que eu possa deixar sqlcla execução em segundo plano e ainda obter a saída na sessão da qual envio os comandos?

..

Editar: Tentando a solução da Germar:

setUpPipes.sh (terminal 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 (terminal 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

Responder1

Uma abordagem que você pode adotar é usar o SPOOLcomando em seu interpretador SQL.

Então, inicie seu pipe nomeado como já estava fazendo:

mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog

Em seguida, faça seu script SQL, mas desta vez habilitando serveroutpute também colocando em spool para um arquivo especificado. Neste exemplo, farei isso apenas para 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

Aqui, também optei por imprimir uma string no arquivo em spool - PROCESS_FINISHED- como uma forma de sinalizar quando o script for concluído, já que o script SQL e o script bash estarão sendo executados lado a lado, com o script bash provavelmente sendo concluído antes o script terminou.

Com isso, posso fazer um script bash ( atomRunner.sh) para enviá-lo para o pipe nomeado:

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

Então executando:

$ ./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

informação relacionada