
Actualmente estoy desarrollando un complemento para compilar código Oracle en mi editor de texto. Las personas que desarrollaron SQL Developer agregaron recientemente una versión de línea de comando sqlcl
. El problema es que se trata de una aplicación Java, y activarla ( jvm
) cada vez que necesito hacer una compilación puede resultar costoso, y algunos informes indican que tarda ~20 segundos.
Una sugerencia que he visto fue usar una canalización con nombre, que si lo hago manualmente, parece funcionar bien.
Terminal 1:
mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog
Terminal 2:
echo "conn hr/[email protected]/xe" > sqlconsole
Y las declaraciones se ejecutan con éxito.
Sin embargo, el problema con esto es que en la terminal 2, no obtengo ninguno de los resultados de la terminal 1 (que quiero).
..
encontré estoartículosobre la lectura de la salida de una canalización con nombre, sin embargo, incluso con eso, la salida sqlcl
no se redirige (y, al escribir esto, parece haber roto la 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 algún enfoque mejor que pueda adoptar, de modo que pueda dejar sqlcl
la ejecución en segundo plano y aún obtener el resultado en la sesión desde la que envío los comandos?
..
Editar: Probando la solución 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
compilarOracle.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
Respuesta1
Un enfoque que podría adoptar es utilizar el SPOOL
comando en su intérprete de SQL.
Entonces, inicia tu canalización con nombre como ya lo estabas haciendo:
mkfifo sqlconsole
tail -f sqlconsole | /opt/sqlcl/bin/sql /nolog
A continuación, cree su secuencia de comandos SQL, pero esta vez habilitándola serveroutput
y también poniendo en cola un archivo específico. En este ejemplo, lo haré simplemente 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
Aquí, también he optado por imprimir una cadena en el archivo en spool - PROCESS_FINISHED
- como una forma de marcar cuando el script ha finalizado, ya que el script SQL y el script bash se ejecutarán uno al lado del otro, y es probable que el script bash se complete antes. El guión ha terminado.
Con eso, puedo crear un script bash ( atomRunner.sh
) para enviarlo a la tubería con nombre:
#!/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
Luego ejecutando:
$ ./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