2010-09-22 98 views
2

我有一個程序,它被調用其他程序和處理孩子的輸出,即:如何在Perl中對管道進行非阻塞式讀取?

my $pid = open($handle, "$commandPath $options |"); 

現在,我已經嘗試了幾種不同的方法從手柄到讀不與很少或根本沒有成功的阻止。

我找到的相關問題:

但他們從問題的困擾:

  • ioctl一貫崩潰的perl
  • sysread 0字節的塊(常見)

我不知道如何去解決這個問題。

+0

這是Windows? – mob 2010-09-22 21:51:58

+0

請參閱[這個答案](http://stackoverflow.com/questions/1530592/why-does-my-perl-sysread-block-when-reading-from-a-socket/1532251#1532251) - 使用'選擇()'來確定是否有可供讀取的數據。 – Ether 2010-09-22 21:52:58

+0

@其他選擇不能在窗口上的文件句柄上工作 – tzenes 2010-09-22 21:56:35

回答

4

管道在Windows上的功能與在Unix-y系統上不同。你不能在它們上使用4個參數select並且默認容量很小。

您最好嘗試基於套接字或文件的解決方法。

$pid = fork(); 
if (defined($pid) && $pid == 0) { 
    exit system("$commandPath $options > $someTemporaryFile"); 
} 
open($handle, "<$someTemporaryFile"); 

現在你有蠕蟲的一對夫婦更罐處理 - 運行waitpid當後臺進程已停止製作輸出定期檢查,要求seek $handle,0,1清除EOF條件你讀之後,從$handle,清理臨時文件,但它的作品。

我寫了Forks::Super模塊來處理像這樣的問題(以及其他許多問題)。對於這個問題,你會使用它像

use Forks::Super; 
my $pid = fork { cmd => "$commandPath $options", child_fh => "out" }; 
my $job = Forks::Super::Job::get($pid); 
while (!$job->is_complete) { 
    @someInputToProcess = $job->read_stdout(); 
    ... process input ... 
    ... optional sleep here so you don't consume CPU waiting for input ... 
} 
waitpid $pid, 0; 
@theLastInputToProcess = $job->read_stdout(); 
+0

@mobrule我的理解是我不能在文件句柄上使用select,所以這只是重新創建了我現在使用的相同問題。 – tzenes 2010-09-22 22:02:15

+0

您不需要在文件句柄上使用select。讀取一個耗盡的文件句柄將會返回'undef'而不會阻塞,然後可以調用'seek HANDLE,0,1'來清除eof條件並再次讀取它。 – mob 2010-09-22 22:05:29

+0

@mob我會不得不尋求我已經讀了多遠?或者它能處理? – tzenes 2010-09-22 22:08:00