web-dev-qa-db-ja.com

名前付きパイプでのOracleコンソールアプリケーションからの出力のリダイレクト

現在、テキストエディタでOracleコードをコンパイルするプラグインを開発しています。 SQL Developerを開発した人々は最近、コマンドラインバージョンsqlclを追加しました。問題は、これはJavaアプリケーション-そして、これを起動する(jvm)をコンパイルする必要があるたびに高価になる可能性があることです-それが〜20秒。

私が見た提案の1つは、名前付きパイプを使用することでした。これを手動で実行すると、うまくいくように見えます。

ターミナル1:

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

ターミナル2:

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

そして、ステートメントは正常に実行されます。

ただし、これに関する問題は、ターミナル2で、ターミナル1から出力が得られないことです(これは必要です)。

..

私はこれを見つけました 記事 名前付きパイプからの出力の読み取りについてですが、それでもsqlclからの出力はリダイレクトされません(そして、これを書いているように、壊れているようです)入力)

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

ターミナル1:

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

ターミナル2:

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

sqlclをバックグラウンドで実行したまま、コマンドを送信するセッションで出力を取得できるようにするための、より良いアプローチがありますか?

..

編集:Germarのソリューションを試す:

setUpPipes.sh(端末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(端末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

2
trent

あなたが取ることができる1つのアプローチは、SQLインタプリタでSPOOLコマンドを利用することです。

そのため、名前付きパイプを既に開始していたように開始します。

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

次に、SQLスクリプトを作成しますが、今回はserveroutputを有効にし、指定したファイルにスプールします。この例では、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

ここでは、スプールファイルに文字列を出力することも選択しました-PROCESS_FINISHED-スクリプトの終了時にフラグを立てる方法として。SQLスクリプトとbashスクリプトは並行して実行されるため、bashスクリプトはスクリプトが終了する前に完了する可能性があります。

それで、bashスクリプトを作成できます(atomRunner.sh)名前付きパイプに送信するには:

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

次に実行します:

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