我有一个标量,我想输入 open3 作为输入。例如
my $sql = "select * from table;";
open( SQL, "<", \$sql );
my ($output);
open3( '<&SQL', $output, $output, "mysql -h 127.0.0.1" );
但是,open3
它位于不同的模块中:
package main;
use Example::Runner;
my $sql = "select * from table;";
open( my $in_handle, "<", \$sql );
my ($out_handle);
Example::Runner::run( $in_handle, $out_handle, $out_handle
'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
我有一个可以从中读取的参考资料中<$in>
,但我需要的是我可以加上前缀的东西,'<&'
以便 open3 将它用作STDIN
它执行的命令。知道我如何将对句柄的引用转换为 open3 可以用于它的东西STDIN
吗?
编辑:
很明显,我的人为示例还不够……我不直接使用 {{DBI}} 的原因是这段代码实际上是我用于无足迹自动化的更大代码体的一部分。换句话说,我有一个由 30 多台服务器组成的环境,我的管理员没有安装任何特殊工具(只是 RHEL 5/6 中的标准工具)。这些服务器分为服务器集(db、app、web)、每个环境(local、dev、qa、beta、prod)、每个项目(...)。无论如何,一项非常常见的任务是将数据库从一个地方复制到另一个地方。我们使用类似于以下的命令来完成此操作:
use IPC::Open3::Callback::CommandRunner;
use IPC::Open3::Callback::Command qw(command pipe_command);
my $source_config = {hostname => 'proj1-prod-db', sudo_username => 'db'};
my $dest_config = {hostname => 'proj1-prod-db', sudo_username => 'db'};
my $command_runner = IPC::Open3::Callback::CommandRunner->new();
$command_runner->run_or_die( pipe_command(
command( "mysqldump dbname", $source_config ),
command( "mysql dbname", $dest_config ) ) );
# runs: ssh proj1-prod-db "sudo -u db mysqldump dbname" | ssh proj1-dev-db "sudo -u db mysql dbname"
这是将我们的生产数据库克隆回开发环境的最基本版本(更典型的版本包括每个命令上的许多开关和中间的许多管道命令)。所以,我围绕这个(IPC::Open3::Callback::*)编写了一个抽象库。在此过程中,我们遇到了需要执行一些在复制数据库后需要运行的 SQL 命令。因此,我们添加了运行任意 SQL 脚本集的功能(基于克隆操作的源和目标)。我可以用这样的命令运行它们:
$command_runner->run_or_die( pipe_command(
"cat $post_restore",
command( "mysql dbname", $dest_config ) ) );
但是我遇到了需要修改 SQL 脚本的一些内容,所以我想把它吞进去,做一些工作,然后将它提供给$command_runner
as STDIN
。也就是说,我尝试使用fileno来处理这个问题:
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);
}
但如果$in_handle
是标量 ref,它就行不通了。不管怎样,这就是说来话长了。