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

如何在Perl中异步运行系统命令?

  •  10
  • Joel  · 技术社区  · 15 年前

    我目前有一个Perl脚本,它在系统上运行一个外部命令,收集输出,并根据返回的内容执行一些操作。现在,下面是我如何运行这个命令(其中$cmd是带有命令设置的字符串):

    @output = `$cmd`;
    

    我想更改这个命令,所以如果命令挂起并且在这么长时间后没有返回值,那么我就终止该命令。我该如何异步运行这个呢?

    3 回复  |  直到 15 年前
        1
  •  8
  •   Neil Neely    15 年前

    如果您真的只需要对给定的系统调用设置超时,那么这比异步编程要简单得多。

    您所需要的只是eval()块内的alarm()。

    下面是一个示例代码块,它将这些代码放入可以放入代码中的子例程中。这个例子调用sleep,所以输出并不令人兴奋,但它确实向您展示了您感兴趣的超时功能。 运行输出为:

    /bin/sleep 2故障:超时 /第15行超时。

    $ cat time-out
    #!/usr/bin/perl
    
    use warnings;
    use strict;
    my $timeout = 1;
    my @cmd = qw(/bin/sleep 2);
    my $response = timeout_command($timeout, @cmd);
    print "$response\n" if (defined $response);
    
    sub timeout_command {
            my $timeout = (shift);
            my @command = @_;
            undef $@;
            my $return  = eval {
                    local($SIG{ALRM}) = sub {die "timeout";};
                    alarm($timeout);
                    my $response;
                    open(CMD, '-|', @command) || die "couldn't run @command: $!\n";
                    while(<CMD>) {
                            $response .= $_;
                    }
                    close(CMD) || die "Couldn't close execution of @command: $!\n";
                    $response;
            };
            alarm(0);
            if ($@) {
                    warn "@cmd failure: $@\n";
            }
            return $return;
    }
    
        2
  •  12
  •   tsee    15 年前

    有很多方法可以做到这一点:

    • 您可以使用fork(perldoc-f fork)完成此操作。
    • 或者使用线程(Perldoc线程)。这两种方法都使得将返回的信息传递回主程序变得困难。
    • 在支持它的系统上,您可以设置一个警报(perldoc-f警报),然后在信号处理程序中进行清理。
    • 您可以使用事件循环,如PoE或CORO。
    • 您可以使用open()或分别使用open2或open3(参见ipc::open2、ipc::open3)来启动程序,而不是通过文件句柄获取stdout/stderr。对其运行非阻塞读取操作。(perldoc-f select和google“perl nonblocking read”)。
    • 作为openx()的更强大的变体,请查看ipc::run/ipc::cmd。
    • 可能是半夜我想不起来的吨。
        3
  •  1
  •   hillu    15 年前

    如果外部程序不接受任何输入,请在 perlipc MangPix:

    这里有一个安全的背景或管道,可以阅读:

    使用示例代码并用警报对其进行保护(也在 Perlic公司 )