
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 jvm
ich 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 sqlcl
wird 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 sqlcl
im 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
SPOOL
Sie 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 serveroutput
das 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_FINISHED
als 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