2010-06-08 77 views
4

我試圖將文件從遠程網站流式傳輸到本地命令,並且在嘗試檢測錯誤時遇到了一些問題。wget不行爲通過IPC :: Open3 vs bash

的代碼看起來是這樣的:

use IPC::Open3; 

my @cmd = ('wget','-O','-','http://10.10.1.72/index.php');#any website will do here 

my ($wget_pid,$wget_in,$wget_out,$wget_err); 
if (!($wget_pid = open3($wget_in,$wget_out,$wget_err,@cmd))){ 
    print STDERR "failed to run open3\n"; 
    exit(1) 
} 
close($wget_in); 
my @wget_outs = <$wget_out>; 
my @wget_errs = <$wget_err>; 
print STDERR "wget stderr: ".join('',@wget_errs); 
#page and errors outputted on the next line, seems wrong 
print STDERR "wget stdout: ".join('',@wget_outs); 

#clean up after this, not shown is running the filtering command, closing and waitpid'ing 

當我直接在命令行運行wget命令和stderr重定向到一個文件中,一些理智的發生 - 在標準輸出將下載的頁面中, stderr將包含有關打開給定頁面的信息。

wget -O - http://10.10.1.72/index.php 2> stderr_test_file 

當我通過open3運行的wget,我得到兩個頁面並在標準輸出混合在一起的信息。我期望的是一個流中的加載頁面和另一個來自wget的STDERR。

我可以看到我已經簡化了代碼,以至於不清楚爲什麼我要使用open3,但總體計劃是我想將stdout按照我收到的方式傳輸到另一個過濾程序,然後最後,我要從wget和過濾程序中讀取stderr,以確定是否出錯。

    其他重要事情:
  • 我試圖避免將wget'd數據寫入文件,然後將該文件過濾到另一個文件,然後讀取輸出。
  • 重要的是,我能夠看到出了什麼問題,而不僅僅是閱讀$? >> 8(即我必須告訴用戶,嘿,IP地址是錯誤的,或不是正確的一種網站,或其他)。
  • 最後,我選擇system/open3/exec而不是其他perl-isms(即反引號),因爲有些輸入是由不可信用戶提供的。
+0

@DVK - 我不確定你的意思?在STDIN上喂wget?我不確定有什麼我需要給它? – Ryley 2010-06-08 21:07:09

+0

好吧,試過了,通過bash shell,stdout和stderr仍然是可分離的... – Ryley 2010-06-08 21:33:32

回答

3

你傳遞一個明確的值作爲錯誤句柄參數open3,並作爲IPC::Open3說:

如果CHLD_ERR是假的,或同一文件描述符CHLD_OUT,然後STDOUT和標準錯誤孩子在同一個文件句柄(這意味着autovivified詞彙不能用於STDERR文件句柄,見概要)...

解決方法是初始化$wget_err送致電open3

my ($wget_pid, $wget_in, $wget_out, $wget_err); 
use Symbol qw(gensym); 
$wget_err = gensym(); 
if (!$wget_pid = open3(...)) { ... 
+1

aaand,這就是我實際上並沒有RTFM獲得的內容......我讀了Open2文檔,後來意識到我需要在此過程中使用STDERR,並沒有讀過Open3文檔的第一行。 – Ryley 2010-06-08 22:19:18