簡體   English   中英

IPC :: Open3在Apache下運行失敗

[英]IPC::Open3 Fails Running Under Apache

我有一個模塊使用IPC :: Open3(或IPC :: Open2,兩者都表明這個問題)來調用外部二進制文件(在這種情況下是bogofilter)並通過子輸入文件句柄輸入一些輸入,然后從中讀取結果子輸出句柄。 在大多數環境中運行時,代碼工作正常。 但是,此模塊的主要用途是在Apache 2.2.6下運行的Web服務中。 在那種環境下,我得到了錯誤:

不能fdopen STDOUT:參數無效

這只在代碼在Apache下運行時才會發生。 以前,代碼構造了一個非常復雜的命令,其中包含輸入的here-document,並使用back-ticks運行它。 雖然有效,但速度非常慢,並且容易以獨特和令人困惑的方式打破。 我不想重新使用舊版本,但我無法解決這個問題。

可能是因為mod_perl 2關閉STDOUT? 我剛剛發現了這個並發布了它:

http://marc.info/?l=apache-modperl&m=126296015910250&w=2

我認為這是一個令人討厭的錯誤,但到目前為止似乎沒有人關心它。 如果您的問題是相關的並且您希望它得到關注,請在mod_perl列表上發布一個跟進。

喬恩

警告Emptor:我不是一個perl巫師。

正如@JonathanSwartz所說,我認為問題是apache2 mod_perl會關閉STDIN和STDOUT。 這與IPC :: Open3正在做的事情無關,但它有一個錯誤,在這里描述

總而言之(這是我不太清楚的部分),open3嘗試將子進程STDIN / OUT / ERR與您的進程匹配,或者如果那是請求則重復它。 由於打開('>&= X')的一些未記錄的方式有效,它通常可以正常工作,除非關閉STDIN / OUT / ERR。

另一個深入細節的鏈接

一種解決方案是修復IPC :: Open3,如兩個鏈接中所述。 另一個對我有用的是暫時在你的mod_perl代碼中打開STDIN / OUT,然后關閉它:

my ($save_stdin,$save_stdout);
open $save_stdin, '>&STDIN';
open $save_stdout, '>&STDOUT';
open STDIN, '>&=0';
open STDOUT, '>&=1';

#make your normal IPC::Open3::open3 call here

close(STDIN);
close(STDOUT);
open STDIN, '>&', $save_stdin;
open STDOUT, '>&', $save_stdout;

另外,我注意到網絡上有很多關於IPC :: Run3遭遇同樣問題的抱怨,所以如果有人遇到同樣的問題,我懷疑同樣的解決方案會起作用。

Bogofilter為垃圾郵件/非垃圾郵件返回不同的退出代碼。

您可以通過將stdout重定向到/ dev / null來“修復”此問題

system("bogofilter < $input > /dev/null") >> 8;

將返回0表示垃圾郵件,1表示非垃圾郵件,2表示未知(>> 8表示因為perl幫助糾正退出代碼,這可以修復損壞)。

注意:缺少環境也可能會阻止bogofilter找到其wordlist,因此也明確地傳遞它:

system("bogofilter -d /path/to/.bogofilter/ < $input > /dev/null") >> 8;

(其中/path/to/.bogofilter包含wordlist.db)

你不能檢索bogofilter給出的實際評級,但它確實能為你提供一些東西。

如果您的代碼只在Linux / Unix系統上運行,那么編寫一個不會失敗的open3替換是很容易的,因為STDOUT不是真正的文件句柄:

sub my_open3 {
    # untested!
    pipe my($inr), my($inw) or die;
    pipe my($outr), my($outw) or die;
    pipe my($errr), my($errw) or die;
    my $pid = fork;
    unless ($pid) {
        defined $pid or die;
        POSIX::dup2($inr, 0);
        POSIX::dup2($outw, 1);
        POSIX::dup2($errw, 2);
        exec @_;
        POSIX::_exit(1);
    }
    return ($inw, $outr, $errr);
}

my ($in, $out, $err) = my_open3('ls /etc/');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM