在命名管道中重定向 Oracle 控制台应用程序的输出

在命名管道中重定向 Oracle 控制台应用程序的输出

我目前正在开发一个插件,用于在我的文本编辑器中编译 Oracle 代码。开发 SQL Developer 的人最近添加了一个命令行版本sqlcl。问题是,这是一个 Java 应用程序 - 每次我需要进行编译时启动它(jvm)可能会很昂贵 - 一些报告称它需要大约 20 秒。

我看到的一个建议是使用命名管道,如果我手动执行此操作,似乎效果很好。

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

答案1

您可以采取的一种方法是利用SPOOLSQL 解释器中的命令。

因此,按照您已经做的方式启动命名管道:

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

相关内容