如何使操作系统命令的标准错误以“!”运行转到 Sql*plus 线轴?

Posted

技术标签:

【中文标题】如何使操作系统命令的标准错误以“!”运行转到 Sql*plus 线轴?【英文标题】:How to make stderr of OS commands ran with "!" go to Sql*plus spool? 【发布时间】:2013-08-07 11:47:04 【问题描述】:

背景

我有一个很长的 Sql*plus 脚本,由于某种原因需要使用感叹号语法运行一些 unix 命令。

我写入一个假脱机以便在进程结束时有一个日志文件。

问题在于,如果操作系统命令失败,stderr 会丢失并且不会转到假脱机文件。

示例代码

spool mylog.txt
!echo alter user xxx identified by yyyy;
alter user xxx identified by yyyy;
!echo cp file1 folder1/
!cp file1 folder1/
!echo alter user yyy identified by xxx;
alter user yyy identified by xxx;
!echo cp file2 folder2/
!cp file2 folder2/
spool off

如果一个cp 失败了,我不会只看mylog.txt 就知道

显然,执行!cp file1 folder1/ &> mylog.txt 只会以不可预知的方式搞乱被假脱机的日志。

问题

为了将 unix 命令的 stderr 写入到 spooled 到的文件中,可以做些什么?

更新

我尝试了 lc.'s 建议,在每个 cp 命令的末尾附加 2>&1 以便将 stderr 重定向到 stdout 但我得到了这个:

Enter value for 1:

更新 2

SET DEFINE OFF 使其不提示输入值。它让我发现不仅 stderr 没有被假脱机:stdout 也没有。似乎一切都用“!”执行是不可假脱机的

【问题讨论】:

【参考方案1】:

其实stdout和stderr并没有丢失,只是不会进入spool文件中。

给定脚本echo.sql

spool sql.out
select 1 from dual ;
!echo 1
!invalid command
spool off

如果您从 shell 启动脚本:

sqlplus *connect string*  @echo.sql > host.out 2> host.err

您将在sql.out 中获得sql 命令的输出,在host.out 中获得echo 的输出,在host.err 中获得错误消息。如果您以非交互方式启动脚本 - 从 cron 或其他东西 - 您必须像执行任何其他非 sql*plus 脚本一样捕获 stdout/stderr。

编辑关于评论

使用脚本文件中的选项SET TERMOUT ON,您将在假脱机文件和标准输出中都有sql命令的输出。

所以最后,如果你想要一个文件中的所有内容,你可以这样调用你的脚本:

sqlplus *connect string*  @echo.sql &>echo.log

您仍然会在 spool 文件中仅获得 sql 的输出。

【讨论】:

问题是我需要生成一个日志。在日志中,条目的顺序必须与它们发生时的顺序相同。在一个文件中有 sql 输出,在另一个文件中有非 sql 输出对我没有帮助。在同一文件的末尾附加非 sql 输出也不是正确的日志。 您的回答以及 lc. 的回答引导我找到了解决方案。不过,我会接受你的,因为它更完整并且用于数据化的解释。我终于从 sql 文件中删除了 spool 命令,并通过 bash 使用sqlplus *connect string* @echo.sql 2>&1 | tee -a echo.log 生成了日志。这样我就可以看到当我以交互方式运行它时会发生什么,并且还可以得到一个包含 stderr、sdtout 和 Sql*plus 输出的日志。【参考方案2】:

您可以将2>&1 附加到每个命令以将stderr 重定向到stdout。

【讨论】:

我刚测试过,提示Enter value for 1: 顺便说一下,stdout 也不会被写入线轴。 以上内容应该适用于 bash。你碰巧知道! 正在使用哪个shell? (AFAIK,stdout 就是写入 spool 的东西,这里的问题在于 stderr 不是。因此解决方案应该是将 stderr 重定向到 stdout) 这是 Bash。问题是 sqlplus 将 &1 视为参数,因为 sql 脚本中的参数遵循 &1、&2 等形式。 这很奇怪。根据this FAQ,! 不应该执行变量替换(而HOST 会)。您可以尝试 SET DEFINE OFF 禁用提示(除非您在其他地方需要)【参考方案3】:

如果您想将 shell 命令输出发送到您的 sqlplus 假脱机文件,当 SPOOL 锁定文件以进行写入时,您无法执行此操作。以下是对我有用的 .sql 脚本中的序列:

SPOOL out.log

...这里有sql的东西...

阀芯关闭

主机 ps -eaf | grep 1>>out.log

SPOOL out.log 追加

...更多的 sql 东西...

【讨论】:

以上是关于如何使操作系统命令的标准错误以“!”运行转到 Sql*plus 线轴?的主要内容,如果未能解决你的问题,请参考以下文章

导入 python 模块以使脚本能够从命令行运行

如何以编程方式使文本可选择并提供弹出菜单以转到另一个应用程序

以编程方式使后退按钮转到上一个视图

LINUX 标准错误输出重定向

虚拟机里怎么开始linux系统,打startx命令提示错误

如何使cmd运行命令为中文提示