
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 sqlcl
nã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 sqlcl
a 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 SPOOL
comando 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 serveroutput
e 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