2009-11-18 91 views
0

我有這個舊的Perl腳本應該充當基於HTTP的客戶端和非HTTP Java服務器之間的代理類:客戶端將一些數據POST到此Perl腳本和腳本將依次調用Java服務器,獲取響應並將其返回給客戶端。mod_perl並在子進程中繼承STDIN

Perl的一部分調用這樣的服務器:

$servervars = "-DREMOTE_HOST=$ENV{'REMOTE_HOST'}"; 
#(a few other server variables passed this way) 

system "java $servervars -cp /var/www javaserver"; 

,然後Java服務器會去:

InputStream serverData = System.in; 
serverData.read(); //and read, and read it on 
//.... 
//print response: 
System.out.print("Content-type: application/octet-stream\n\n"); 
System.out.write(...); 

問題是,當Perl腳本是通過CGI調用這個工作得很好,但如果Perl腳本是由mod_perl(實際上是mod_perl2)來處理的話,它根本不起作用。顯然,Java部分不會從Perl獲得STDIN(serverData.available()返回0),並且Perl不會返回STDOUT。後者可以通過打印`java ...`(即反引號)而不是系統「java ...」來彌補,但我不知道如何處理STDIN。

Perl腳本本身能夠讀取STDIN中的POST數據。我也嘗試生成一個測試Perl腳本而不是Java應用程序,並且也沒有得到父腳本的STDIN。

從描述判斷,從Apache2 :: SubProcess的spawn_proc_prog可以做到這一點(即將POST數據作爲STDIN傳遞給子進程並取回子進程的輸出),但它似乎不工作我運行任何東西,但另一個Perl腳本。

有什麼辦法讓子進程繼承父腳本的STDIN嗎?我可以在Perl腳本中讀取流並將其內容作爲命令行參數傳遞,但我認爲這將成爲命令行長度限制的主題,有時可能會有很多數據(如圖片),所以我真的想弄清楚如何繼承流。

回答

1

哇,我希望這是來自客戶端的低容量負載。在mod_perl中,stdin綁定到客戶端的套接字句柄,並與stdout相同。因此,要將STDOUT設置爲java進程,需要將* STDOUT設置爲Java服務器的套接字句柄,或者在您的情況下,因爲您正在打開進程,請執行select STDOUT並可能通過設置$ |來使其無緩衝。另外,當您想要將數據流式傳輸回客戶端時,您需要直接寫入客戶端的套接字句柄或將STDOUT重置爲其原始值。

+0

是的,我認爲這是爲了相當低的容量負載。 你能更具體地瞭解究竟應該做什麼?如何在Perl端選擇幫助 - 子進程在Java中,它不會關心Perl的默認流。 此外,Java服務器沒有任何開放式套接字 - 至少沒有明確指出 - 它從STDIN(它可能被實現爲下面的套接字,我不知道)讀取它需要的所有東西。 – 7macaw 2009-11-18 18:27:45

+0

所以你的Java進程不聽任何網絡通訊,那它就不是一個「服務器」。它所做的只是從STDIN讀取。在你的perl腳本中這樣做,我的$ sh = STDOUT;打開(JFH,「| java $ servervars -cp/var/www javaserver」); * STDOUT = JFH;然後從perl執行所有的寫操作,因爲你的java進程從STDIN中讀取,它將讀取你從perl寫入的所有內容,因爲你以這種方式打開了你的java進程。寫完之後,你已經將你的perl的STDOUT重置回原來的輸出文件句柄,這是你保存在$ sh – 2009-11-18 20:59:00

+0

中的客戶端套接字句柄或者我想我可以打印JFH「whatever」而不是將STDOUT複製到變量。 謝謝,這似乎工作 - 雖然現在我不知道如何獲得Java的輸出回來?我可以將它重定向到一個文件中,如打開(JFH,「| java $ servervars -cp/var/www javaserver>/tmp/somefile。txt「);這可能就足夠了,但我想知道是否有辦法以某種方式將它作爲一個流。 – 7macaw 2009-11-20 00:01:50