入力として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}} を直接使用しない理由は、このコードが実際にはフットプリントのない自動化に使用するより大きなコード本体の一部だからです。つまり、管理者が特別なツールをインストールしていない (RHEL 5/6 に標準装備されているものだけ) 30 台以上のサーバーの環境があります。これらのサーバーは、各環境 (local、dev、qa、beta、prod)、各プロジェクト (...) ごとに、一連のサーバー (db、app、web) に分割されます。とにかく、非常に一般的なタスクの 1 つは、データベースをある場所から別の場所にコピーすることです。次のようなコマンドでそれを実現します。
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
、スカラー参照の場合は機能しません。とにかく、それは長い話です。