代码之家  ›  专栏  ›  技术社区  ›  ldrg

在IPC::Run中使用正确的Perl数组引用

  •  0
  • ldrg  · 技术社区  · 4 年前

    我正在努力让这段Perl代码正常工作,我相信我只需要正确地引用。如果您能提供关于如何使用引用的任何反馈,我将不胜感激。但是,如果没有API的更改,这段代码就无法正常工作,那么我也希望您能提供关于如何更改周围的API以支持我需要的数据类型的反馈。

    我正在尝试向PostgreSQL测试套件添加一个新测试。所讨论的代码运行一个子流程,并将流程参数存储在散列中的数组文本中。例如:

    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(@_);
    }
    

    为了编写我的测试用例,我 将命令的输出通过管道传输到不支持查找的文件描述符。看起来IPC::Run模块为您提供了管道支持。以下是文档的示例:

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

    但是我尝试了很多不同的方法来构造我的数组文字,但没有一种有效。例如,我试过这个,我相信它给了我一个机会 ARRAY(0xFFFFFFFF) 错误:

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

    我如何让这段代码设置多个子流程和管道?

    更新:我尝试了池上的建议: command_ok 函数只能向其传递两个参数,因此这不起作用(必须为第一个参数传递数组引用)。

    更新:打开IPC:Run的调试功能,我可以看到它试图解释我的命令行。它没有取消对数组的引用,而是试图将其字符串化(?)将该字符串作为可执行文件执行:

    1070 IPC::Run 0002 01234567890- [#11(59856)]: parsing [ 'ARRAY(0x7ff3016f1090)', '|', 'ARRAY(0x7ff3016f1510)', '>/Users/david/src/pg_bug/postgres/foo' ]
    
    0 回复  |  直到 4 年前
        1
  •  1
  •   ikegami    4 年前

    你实际上在做以下事情: [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}
      

      在这两种情况下 -> 可以省略,因为它位于两个索引之间。

    推荐文章