Redirigir la salida de una aplicación de consola de Oracle en una canalización con nombre

Redirigir la salida de una aplicación de consola de Oracle en una canalización con nombre

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 sqlclno 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 sqlclla 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 SPOOLcomando 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 serveroutputy 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

información relacionada