在 perl 中打开一个管道进程(sqlplus)并从查询中获取信息?

Posted

技术标签:

【中文标题】在 perl 中打开一个管道进程(sqlplus)并从查询中获取信息?【英文标题】:Open a piped process (sqlplus) in perl and get information from the query? 【发布时间】:2011-02-03 13:50:41 【问题描述】:

基本上,我想open 使用 Perl 连接到 sqlplus 的管道,发送查询,然后从查询中取回信息。

当前代码:

open(PIPE, '-|', "sqlplus user/password@server_details");

while (<PIPE>) 
    print $_;

这让我可以跳转到 sqlplus 并运行我的查询。

我无法弄清楚如何让 Perl 发送 sqlplus 查询(因为它始终是相同的查询),一旦完成,我如何才能将信息写回到我的 Perl 脚本中的变量中?

PS - 我知道 DBI... 但我想知道如何使用上述方法进行操作,尽管它很不优雅:)


对代码进行了一些更改,现在我可以将查询发送到 sqlplus,但是它断开连接...我不知道如何从中获取结果。

my $squery = "select column from table where rownum <= 10;"

# Open pipe to sqlplus, connect to server...
open(PIPE, '|-', "sqlplus user/password@server_details") or die "I cannot fork: $!";
# Print the query to PIPE?
print PIPE $squery;

会不会是从 sqlplus 中获取 STDOUT,然后使用 Perl(父)脚本存储它?

基本上,我想将它存储在一个数组中以供稍后解析。

流程图:

Perl 脚本(父)-> 打开管道到 sqlplus(子)-> 在管道上打印查询-> sqlplus 在屏幕上输出结果(STDOUT?)-> 将 STDOUT 读入 Perl 脚本中的数组(父)


编辑:使用这种方法将进程分叉到 sqlplus 中可能不可行,我必须使用 DBI。等着看有没有人回答...

【问题讨论】:

【参考方案1】:

忘记屏幕抓取,Perl 有一个完美的 cromulent database interface。

【讨论】:

刚刚修改了我的问题。无论如何,感谢您指出!【参考方案2】:

我想你可能想要IPC::Run。您将使用start 函数来让事情顺利进行:

 my $h = start \@cat, \$in, \$out;

您可以将您的查询分配给$input 变量并泵送,直到您在$output 变量中获得预期的输出。

$in = "first input\n";

## Now do I/O.  start() does no I/O.
pump $h while length $in;  ## Wait for all input to go

## Now do some more I/O.
$in = "second input\n";
pump $h until $out =~ /second input/;

## Clean up
finish $h or die "cat returned $?";

此示例是从 CPAN 页面窃取的,如果您需要更多示例,请访问该页面。

【讨论】:

我可以不安装这个模块/库吗? @Az,是的,您可以(请参阅核心模块 IPC::Open2),但上帝帮助第一次尝试它的人,大约在第四次重写之后,因为您发现了一些奇怪的晦涩行为你永远不会想到会发生你会希望你只是使用一个经过良好测试的模块。【参考方案3】:

如果您的查询是静态的,请考虑将其移动到它自己的文件中并让sqlplus 加载并执行它。

open(my $pipe, '-|', 'sqlplus', 'user/password@server_details', '@/path/to/sql-lib/your-query.sql', 'query_param_1', 'query_param_2') or die $!;

while (<$pipe>) 
    print $_;

【讨论】:

只是检查一下:-| 之后的所有“参数”都是输入 bash 进程的参数,对吧?对于open,这只是一个巨大的争论,yarp? @Az,不完全是,提供 open 一个列表而不是单个命令名称 bash 永远不会被调用。这限制了相当多的代码注入向量,但也阻止您在命令本身中使用bash 的功能。你能提供比“没有工作”更详细的信息吗?有错误输出吗? sqlplus 预计您将在文件执行后以交互方式使用它,因此您可能需要以 exit 结束 sql 文件以终止 while 循环。您还可以从与 Perl 脚本分开的命令行中测试该命令,以查看它是 Perl 方面还是 sqlplus 方面的问题。 密码中有一些字符需要使用 `` 来分隔,所以单引号不能很好地配合它。 对此感到抱歉(我已注销并且发生了随机事件)。 Anyhoo,我很欣赏这个建议,但我真的很想从我卡住的地方继续(更新问题)。 :) (PS - 这是我提到我对 Perl 很陌生的地方)。

以上是关于在 perl 中打开一个管道进程(sqlplus)并从查询中获取信息?的主要内容,如果未能解决你的问题,请参考以下文章

Perl:当子/管道的文件句柄被别名时,关闭子进程失败

Perl ipc 使用管道从另一个进程启动一个进程的执行

在 Perl 中打开管道是不是涉及 shell?

在 perl 中关闭多个输出管道而不阻塞每个输出管道

管道被 Perl 中的子进程阻塞

为啥子进程中的管道有时会中断,有时不会?