如何使用标量作为perl中open3的输入

如何使用标量作为perl中open3的输入,perl,reference,ipcopen3,Perl,Reference,Ipcopen3,我有一个标量,我想输入到open3中作为输入。比如说 my $sql = "select * from table;"; open( SQL, "<", \$sql ); my ($output); open3( '<&SQL', $output, $output, "mysql -h 127.0.0.1" ); 然后在另一个文件中: package Example::Runner; sub run { my ($in, $out, $err, @command

我有一个标量,我想输入到open3中作为输入。比如说

my $sql = "select * from table;";
open( SQL, "<", \$sql );

my ($output);
open3( '<&SQL', $output, $output, "mysql -h 127.0.0.1" );
然后在另一个文件中:

package Example::Runner;

sub run {
    my ($in, $out, $err, @command) = @_;
    open3( ?, $out, $err, "mysql -h 127.0.0.1" );
}
问题是,在
Example::Runner
中,我有一个可以从
中读取的参考,但我需要的是可以在
前面加上前缀的东西。fileno($err_handle):未定义,
@命令
);
返回($^O=~/MSWin32/)_win_open3(@args):_nix_open3(@args);
}

但是如果
$in_handle
是标量引用,它就不起作用。无论如何,这是一个很长的故事。

open\$var
不起作用,因为它不创建子级可以读取的系统文件句柄

$ perl -E'open(my $fh, "<", \"abc") or die $!; say fileno($fh);'
-1
但这很危险。你正冒着陷入僵局的风险。(当您尝试向其STDIN发送大量[1]数据时,如果孩子尝试向STDOUT或STDERR发送大量[1]数据,则会发生死锁。)要避免此问题,您需要一个
select
循环。这很难。你不想用这么低级的东西。使用或代替
open3
,因为他们会为你做所有的脏活

use IPC::Run3 qw( run3 );
run3($shell_cmd, \$sql, \my $out, \my $err);
更好的是,避免不必要的外壳:

run3([ $prog, @args ], \$sql, \my $out, \my $err);
但是,为什么要使用为人使用而设计的客户机作为界面呢?您可能应该使用


  • 我相信,在某些系统上,相当小的4KB是一个“大”数量,尽管我似乎记得在我的一台Linux机器上,管道有128KiB

  • 我不太明白。你为什么不能给它一个手柄,然后打印到那个手柄上<代码>我的$pid=open3(\*SQL,$output,$output,“mysql-H127.0.0.1”);如果($pid){print SQL();close(SQL);}或保持原始的
    SQL
    并打开(\*SQL2,$output,$output,…);打印SQL2;关闭SQL2@hepcat72,@mob,我试图简化本例中的问题,但原因是它必须在命令开始运行之前存在,或者我用来处理OUT和ERR(以及in ish)的
    IO::Select
    变得不可靠。(这是针对
    IO::Open3::Callback::safe\u open\u 3
    )…IPC::Open3无法做到这一点。使用IPC::Run可以提供一种更灵活的界面,该界面还支持输入/输出的标量和函数。也许我不太明白您到底想做什么,但为什么不使用DBI呢?我过去曾研究过
    IPC::Run
    ,但它阻碍了我。至于为什么不使用
    DBI
    ,我正在尝试运行任意SQL脚本。一个足够简单的脚本可以在<代码>上进行拼凑和拆分和循环,但如果存在函数定义或分隔符切换,或任何其他特定于db的操作,则会中断…恰恰相反,IPC::Run会走极端以支持Windows。但是如果没有
    fork
    select
    ,它会遇到很多障碍。(
    select
    仅适用于Windows中的套接字。)
    sub safe_open3_with {
        my ($in_handle, $out_handle, $err_handle, @command) = @_;
    
        my @args = (
            $in_handle ? '<&' . fileno( $in_handle ) : undef,
            $out_handle ? '>&' . fileno( $out_handle ) : undef,
            $err_handle ? '>&' . fileno( $err_handle ) : undef,
            @command
        );
        return ( $^O =~ /MSWin32/ ) ? _win_open3(@args) : _nix_open3(@args);
    }
    
    $ perl -E'open(my $fh, "<", \"abc") or die $!; say fileno($fh);'
    -1
    
    pipe(local *CHILD_STDIN, local *TO_CHILD)
       or die("Can't create pipe: $!\n");
    
    my $pid = open3($cmd, '<&CHILD_STDIN', local *FROM_CHILD, undef);
    
    print(TO_CHILD do { local $/; <$in> });
    close(TO_CHILD);
    
    use IPC::Run3 qw( run3 );
    run3($shell_cmd, \$sql, \my $out, \my $err);
    
    run3([ $prog, @args ], \$sql, \my $out, \my $err);