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

2

Atualmente, estou desenvolvendo um plug-in para compilar o código do Oracle em meu editor de texto. As pessoas que desenvolveram o SQL Developer adicionaram recentemente uma versão de linha de comando sqlcl . O problema é que esse é um aplicativo Java - e disparar isso ( jvm ) toda vez que preciso fazer uma compilação pode ser caro - com alguns relatórios dele demorando ~ 20 segundos.

Uma sugestão que eu vi foi usar um pipe nomeado, que se eu fizer isso 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 declarações são executadas com sucesso.

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

..

Eu encontrei este artigo sobre a saída de leitura de um canal nomeado, mas mesmo com que, a saída de sqlcl não é redirecionada (e, como está escrito, parece ter quebrado a entrada)

#!/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 fazer - de tal forma que eu possa deixar o sqlcl rodando em segundo plano, e ainda conseguir a saída na sessão que eu envio os comandos?

..

Editar: Tentando a solução de 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

    
por trent 25.11.2015 / 02:18

1 resposta

1

Uma abordagem que você pode fazer é usar o comando SPOOL no seu interpretador SQL.

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

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

Em seguida, faça seu script SQL, mas desta vez ativando serveroutput e também fazendo spool para um arquivo especificado. Neste exemplo, vou apenas fazer isso 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 para o arquivo em spool - PROCESS_FINISHED - como uma forma de sinalizar quando o script foi concluído, já que o script SQL e o script bash serão executados lado a lado, com o script script bash provavelmente concluído antes de o script ser concluído.

Com isso, posso criar um script bash ( atomRunner.sh ) para enviá-lo ao 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

Em seguida, execute:

$ ./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
    
por trent 26.11.2015 / 23:10