簡體   English   中英

使用正確的 Perl 數組引用和 IPC::Run

[英]Using the right Perl array references with IPC::Run

我試圖讓這個 Perl 代碼正常工作,我相信我只需要正確地獲取我的參考。 我將不勝感激有關如何使用引用的任何反饋,但如果在沒有 API 更改的情況下無法使此代碼工作,我還將感謝有關如何更改周圍 API 以支持我需要的數據類型的反饋。

我正在嘗試向 PostgreSQL 測試套件添加一個新測試。 有問題的代碼運行一個子進程並將進程 arguments 存儲在 hash 中的數組文字中。 例如:

my %pgdump_runs = (
    defaults => {
        dump_cmd => [
            'pg_dump', '--no-sync',
            '-f',      "$tempdir/defaults.sql",
            'postgres',
        ],
    },
    # and others
)

該數組被傳遞給一個輔助庫,如下所示:

    $node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} },
        "$run: pg_dump runs");

輔助庫不斷向下傳遞數組:

sub command_ok
{
    my ($cmd, $test_name) = @_;
    my $result = run_log($cmd);

然后最后調用IPC::Run

sub run_log
{
    return IPC::Run::run(@_);
}

要編寫我的測試用例,我必須將 pipe 和 output 的命令發送到不支持查找的文件描述符。 看起來 IPC::Run 模塊為您支持管道。 這是文檔的示例:

run \@cmd1, '|', \@cmd2;

但是我嘗試了很多不同的方法來嘗試構造我的數組文字,但都沒有奏效。 例如,我試過這個,我相信它給了我一個ARRAY(0xFFFFFFFF)錯誤:

        dump_cmd => [
            ['pg_dump', 'db'],
            '|',
            ['pg_restore', 'db2'],
        ],

如何獲取此代碼以使用管道設置多個子流程?

更新:我嘗試了 ikegami 的建議: command_ok function 只能有兩個 arguments 傳遞給它,所以這不起作用(你必須為第一個參數傳遞一個數組引用)。

更新:打開 IPC:Run 的調試功能我可以看到它是如何試圖解釋我的命令行的。 它不是取消對數組的引用,而是嘗試將其字符串化(?)並將該字符串作為可執行文件執行:

1070 IPC::Run 0002 01234567890- [#11(59856)]: parsing [ 'ARRAY(0x7ff3016f1090)', '|', 'ARRAY(0x7ff3016f1510)', '>/Users/david/src/pg_bug/postgres/foo' ]

您正在有效地執行以下操作: [1]

my %pgdump_runs = (
    foo => {
        dump_cmd => [
            ['pg_dump', 'db'],
            '|',
            ['pg_restore', 'db2'],
        ],
    },
);

IPC::Run::run( $pgdump_runs{foo}{dump_cmd} )

這將一個參數傳遞給run ,但您表示您想要實現類似於

run \@cmd1, '|', \@cmd2;

那將需要

IPC::Run::run( @{ $pgdump_runs{foo}{dump_cmd} } )

有幾種方法可以解決這個問題:

  1. 代替

    return IPC::Run::run(@_);

    return IPC::Run::run(@{ $_[0] });
  2. 代替

    run_log($cmd);

    run_log(@$cmd);
  3. 代替

    sub command_ok { my ($cmd, $test_name) = @_; my $result = run_log($cmd); } $node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} }, "$run: pg_dump runs");

    sub command_ok { my $test_name = shift; my $result = run_log(@_); } $node->command_ok("$run: pg_dump runs", @{ $pgdump_runs{$run}{dump_cmd} });
  4. 代替

    dump_cmd => [ ['pg_dump', 'db'], '|', ['pg_restore', 'db2'], ],

    use String::ShellQuote qw( shell_quote ); dump_cmd => join(' ', shell_quote('pg_dump', 'db'), '|', shell_quote('pg_restore', 'db2'), ),

腳注:

  1. 除非你試圖自動激活(你不是),

     \@{ $pgdump_runs{$run}->{dump_cmd} }

    也可以寫成

    $pgdump_runs{$run}->{dump_cmd}

    在這兩種情況下, ->都可以省略,因為它位於兩個索引之間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM