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

问题描述:

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

@output = `$cmd`; 

我想改变这种做法,如果命令挂起,不经过这么多的返回值那么我会杀死这个命令。我将如何去异步运行它?

如果你真的只需要在给定的系统调用上放一个超时,这是一个比异步编程简单得多的问题。

所有你需要的是一个eval()块内部的alarm()。

下面是一个示例代码块,它将这些代码放入可以放入代码的子例程中。该示例调用睡眠等都不是令人兴奋的输出,但不告诉你,你有兴趣的超时功能,运行它的 输出为:

/斌/睡眠2失败:超时在 ./time退房手续线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 [email protected]; 
     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 ([email protected]) { 
       warn "@cmd failure: [email protected]\n"; 
     } 
     return $return; 
} 
+0

谢谢,这是我所寻找的更多。 – Joel 2009-12-03 16:10:59

+0

我认为你需要在死信息中有一个\ n。 (http://perldoc.perl.org/functions/alarm.html) – ddoxey 2013-04-04 05:04:16

有办法做到这一点很多:

  • 您可以用叉子(参阅perldoc -f叉)
  • 或使用线程(线程的perldoc)做到这一点。这两种方法都会使返回的信息难以回到主程序。
  • 在支持它的系统上,您可以设置一个警报(perldoc -f警报),然后在信号处理程序中进行清理。
  • 您可以使用像POE或Coro这样的事件循环。
  • 除了反引号之外,您可以使用open()或open2或open3(参见IPC :: Open2,IPC :: Open3)来启动程序,同时通过文件句柄获取STDOUT/STDERR。在其上运行非阻塞式读取操作。 (perldoc -f选择和可能谷歌“perl nonblocking读”)
  • 作为一个更强大的变种的openX()的,检查出IPC :: Run/IPC :: Cmd。
  • 大概是我在半夜想不到的吨。
+3

在Win32系统当心破'select'只用于插座和与控制台窗口可能奇怪反应工程,wperl(运行在一个非控制台窗口的方式perl的,但对STDIO和子进程有奇怪的影响)。在好的一面,你可以做一个'system(-1,'foo')'。此外,运行64个子项后,某些启动进程的方式失败。 IME,'Win32 :: Process :: Create()'是在bgrnd中运行程序最安全的方法。 – daotoad 2009-11-18 01:10:24

+0

@daotoad,感谢您的评论。我缺乏win32线索表明我唯一知道的是fork()是用线程模拟的,而且你不能使用警报。我猜如果涉及win32,IPC :: Cmd将是一个不错的选择。 – tsee 2009-11-18 08:46:00

如果你的外部程序不带任何输入,寻找在perlipc手册页下面的话:

这里是一个安全的反引号或管开放阅读:

使用示例代码并警告它(这也在perlipc中解释)。