4

使ってます

Server version: Apache/1.3.34 (Debian)
mod_perl - 1.29

STDIN 、STDOUT、およびSTDERRストリームを参照する

#!/usr/bin/perl5
package main;

use strict 'vars';

{
    # Our mighty holy legacy code love to print out message in the middle of operation. Shihh....
    # Let's quietly redirect those message to /dev/null.
    my $nullfh = Apache::gensym( );
    open $nullfh, '>/dev/null' or warn "Can't open /dev/null: $!";
    local *STDOUT = $nullfh;
    print "BYE BYE WORLD";    # Shouldn't show in webpage.
    close $nullfh;
}

print "X BEGIN HELLO WORLD";  # Should show in webpage.

私はそれがいつも働いているわけではないことを理解しています。たとえば、ページを10回更新します。x回、「XBEGINHELLOWORLD」が出力されます。(10-x)時間は何も出力しません。

私はそれがこのように振る舞う理由を見つけることができません。私と同じような問題に遭遇した人がいることを知っていますか?

4

4 に答える 4

6

明示的に保存して復元する必要があります。私の場合はうまくいきます。しかし、その理由はわかりません。

# Take copies of the file descriptors
open OLDOUT, '>&STDOUT';
my $returned_values = 0;
{
    # Our mighty holy legacy code love to print out message in the middle of operation. Shihh....
    # Let's quietly redirect those message to /dev/null.
    local *STDOUT;
    open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!";
    print "BYE BYE WORLD";    # Shouldn't show in webpage.
    close STDOUT;
}
# Restore stdout.
open STDOUT, '>&OLDOUT' or die "Can't restore stdout: $!";
# Avoid leaks by closing the independent copies.
close OLDOUT or die "Can't close OLDOUT: $!";
于 2009-06-30T01:10:39.883 に答える
2

試す:

local $|=1;

print。これはバッファリングをバイパスします。

http://perldoc.perl.org/perlvar.html#HANDLE-%3Eautoflush%28EXPR%29を参照してください

于 2009-06-28T10:38:03.530 に答える
1

それはmod_perlの相互作用であり、STDOUTglobの再割り当てであるに違いありません-Webサーバーでperlの1つのインスタンスを効果的に実行している場合、これlocalにより、スコープ外になったとき、およびさまざまprintなとcloseのが起こります。

これは基本的に私の推測ですが、それが起こっているかどうかはわかりませんので、覚えておいてください。大まかに言えば、これを行うと競合状態は次のようになります。

local *STDOUT = $nullfh;

そしてこれlocalが範囲外になったとき。Webサーバーへのリクエストは(mod_perlを使用しているため)異なるスレッドとして処理され、各スレッドはglobの新しい値を確認できる可能性があると思います。

于 2009-06-28T10:01:25.180 に答える
1

すでに述べたように、バッファリングが最も可能性の高い問題ですが、何らかの理由でそれがうまくいかない場合は、別のアプローチがあります。組み込みの多くの場合無視されるone-argselect()を使用して、印刷出力のデフォルトの出力ファイルハンドルを変更できます。

于 2009-06-28T21:56:09.820 に答える