我目前正在开发一个插件,用于在我的文本编辑器中编译 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
您可以采取的一种方法是利用SPOOL
SQL 解释器中的命令。
因此,按照您已经做的方式启动命名管道:
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