Umleiten der Ausgabe einer Oracle-Konsolenanwendung in einer benannten Pipe

Umleiten der Ausgabe einer Oracle-Konsolenanwendung in einer benannten Pipe

Ich entwickle derzeit ein Plugin zum Kompilieren von Oracle-Code in meinem Texteditor. Die Leute, die SQL Developer entwickelt haben, haben kürzlich eine Befehlszeilenversion hinzugefügt sqlcl. Das Problem ist, dass es sich um eine Java-Anwendung handelt - und es kann teuer sein, diese jedes Mal zu starten, wenn jvmich eine Kompilierung durchführen muss - einigen Berichten zufolge dauert es etwa 20 Sekunden.

Ein Vorschlag, den ich gesehen habe, war die Verwendung einer benannten Pipe. Wenn ich dies manuell mache, scheint das gut zu funktionieren.

Schalter 1:

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

Terminal 2:

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

Und die Anweisungen werden erfolgreich ausgeführt.

Das Problem dabei ist jedoch, dass ich in Terminal 2 keine der Ausgaben von Terminal 1 erhalte (die ich möchte).

..

ich habe das gefundenArtikelüber das Lesen der Ausgabe aus einer benannten Pipe, aber selbst damit sqlclwird die Ausgabe nicht umgeleitet (und scheint, beim Schreiben dieser Zeilen, die Eingabe beschädigt zu haben)

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

Schalter 1:

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

Terminal 2:

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

Gibt es einen besseren Ansatz, den ich wählen kann – etwa den, den ich sqlclim Hintergrund laufen lassen kann und trotzdem die Ausgabe in der Sitzung erhalte, aus der ich die Befehle sende?

..

Bearbeiten: Ich versuche Germars Lösung:

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

KompiliereOracle.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

Antwort1

SPOOLSie könnten beispielsweise den Befehl in Ihrem SQL-Interpreter verwenden .

Starten Sie also Ihre benannte Pipe, wie Sie es bereits tun:

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

Als nächstes erstellen Sie Ihr SQL-Skript, aber aktivieren Sie dieses Mal serveroutputdas Spoolen in eine angegebene Datei. In diesem Beispiel mache ich es nur in 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

Hier habe ich mich auch dafür entschieden, eine Zeichenfolge in die Spooldatei zu drucken – PROCESS_FINISHEDals Markierung, wenn das Skript beendet ist, da das SQL-Skript und das Bash-Skript nebeneinander ausgeführt werden und das Bash-Skript wahrscheinlich vor dem Skript beendet wird.

Damit kann ich dann ein Bash-Skript ( atomRunner.sh) erstellen, um es an die benannte Pipe zu senden:

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

Dann ausführen:

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

verwandte Informationen