2009-11-17 112 views
9

我目前有一個Perl腳本,它在系統上運行一個外部命令,收集輸出,並根據返回的內容執行一些操作。現在,這裏是我如何運行這個(其中$ cmd是用命令設置一個字符串):如何以異步方式在Perl中運行系統命令?

@output = `$cmd`; 

我想改變這種做法,如果命令掛起,不經過這麼多的返回值那麼我會殺死這個命令。我將如何去異步運行它?

回答

8

如果你真的只需要在給定的系統調用上放一個超時,這是一個比異步編程簡單得多的問題。

所有你需要的是一個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

12

有辦法做到這一點很多:

  • 您可以用叉子(參閱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

1

如果你的外部程序不帶任何輸入,尋找在perlipc手冊頁下面的話:

這裏是一個安全的反引號或管開放閱讀:

使用示例代碼並警告它(這也在perlipc中解釋)。