perlの標準エラー出力の扱い方

[上に] [前に] [次に]
B-Cus 1998/01/12(月) 18:22:08
perlで実行した標準エラー出力を処理する方法を教えてください。
また、標準エラー出力のみを受け取る方法を教えてください。


例えば exist-file が存在して、non-exist-fileが存在しないとき、

open(IN,"ls exist-file non-exist-file|);
print <IN>;

とすると出力は 「exist-file」 のみになってしまいます。
標準エラー出力に出力されている
「non-exist-file: No such file or directory」を受け取る
にはどうすればいいでしょうか。

また、標準出力は捨て、標準エラー出力のみを受け取る方法
# 「non-exist-file: No such file or directory」だけを受け取る方法
も教えていただけるとありがたいです。

よろしくお願いします。

miyasiro [E-Mail] 1998/01/13(火) 22:56:30
UNIX はよく知らないんですが、
open(IN,"ls exist-file non-exist-file 2>&1 |");
print <IN>;
でファイルハンドルを切り替えれば、標準エラー出力を受け取れる
んじゃないでしょうか?

open(IN,"ls exist-file non-exist-file |&");
でもいいのかな?

たむら 1998/01/14(水) 11:22:59
質問の答えにはならないのですが、存在するファイルをチェックして
読み込み処理などを行えば、問題ないような気がするんですが。
perlの場合、dirに存在するファイル・ディレクトリを読み込む
opendir/readdir/closedirなどの関数が用意されてます。
たとえば、
opendir(DIR,"./");
while($filename = readdir(DIR) ){
print "$filename\n" if -f $filename;
print "$filename /\n" if -d $filename;
}
close(DIR);
とやれば、lsもどきの表示ができます。詳しい属性やファイル容量が
知りたければ、ファイルテスト演算子やstatを使うと良いのでは。

B-Cus 1998/01/14(水) 15:13:48
ありがとうございます。
 open(IN,"ls exist-file non-exist-file 2>&1 |");
でうまくいきました。
# open(IN,"ls exist-file non-exist-file |&"); はダメでした。

> 質問の答えにはならないのですが、存在するファイルをチェックして
> 読み込み処理などを行えば、問題ないような気がするんですが。

あ、すいません。lsはSTDERRへの出力の例としてあげさせて
いただきました。

print `...`; の行がどうしても動かなくて数時間悩んでしまったの
ですが、実はコアダンプしてました。で、STDERRを表示させれば
そういうことに早く気づいたのではないか、と思いまして質問させて
いただきました。

で、「core dumped」と表示されることを期待して、さっそく試して
みたのですが、うまくいきませんでした(;_;)


それはそれとしてもう一つ質問させてください。
------------------------
#!/usr/local/bin/perl

print "Content-type: text/html\n\n";
print "This is test.\n";

open(OUT,">/etc/passwd") || die "can't open /etc/passwd";
close(OUT);
------------------------

この場合もSTDERRに can't open /etc/passwd と出力されますが、
CGIで実行すると STDERR は捨てられるため表示されません。

こういう perlが出力する STDERRを、STDOUTに振ることはできますか?
コマンドラインからだと
 open(STDERR,">/dev/stdout");
でうまくいったのですが、CGIとして実行すると「Internal Server Error」
となってしまいました。

よろしくお願いします。

miyasiro 1998/01/14(水) 21:59:21
perl自身が出力するエラー表示をスクリプト内で取得するのは無理なんじゃ
ないのかなぁ?
ご希望の方法と使い方が違うかも知れませんが、
gama(http://www2d.biglobe.ne.jp/~gama/cgi/)さんのところの「ふろく」に
「cgi-test.cgi(cgi をテストする CGI です。)」というのがあります。
テストするCGIをdest.cgiとして、別のCGIの中で
open( IN, "./dest.cgi 2>&1 |" );
として、エラー表示を取得するものだったと思います。

とほほ 1998/01/15(木) 13:16:22
die の出力をCGIの結果として返すには、
  #!/usr/local/bin/perl
  open(STDERR, ">&STDOUT");
  $| = 1;
としてみてください。
  close(STDERR);
  open(STDERR, ">-");
でもできると思ったのだけれど、これは駄目だった。

miyasiro 1998/01/15(木) 14:29:58
>  open(STDERR, ">&STDOUT");
>  $| = 1;
なるほど、UNIXはいろいろあるなぁ(manにも記載がありました)。勉強になります。
それと、出力をスクリプトで受けることしか考えてなかったのですが、
STDOUTにしておけば、ブラウザで受けることができますね。これも、うっかり
してました。
(この手は、デバッグ時に大いに役に立ちそうだ!)

B-Cus 1998/01/16(金) 01:10:40
[[解決]]
ありがとうございました。
 open(STDERR, ">&STDOUT");
 $| = 1;
これでうまくいきました。


あとSTDOUT関係の小技ですが…

CGIを作っていて表示がEUCになって化けてしまう。でも全ての
 print "...";

 open(OUT,"|/usr/local/bin/nkf -j");
 print OUT "...";
に変更するのは面倒だというときは、最初に
 open(STDOUT,"|/usr/local/bin/nkf -j");
と書いておけばいい、というのがありますね。


というわけで一連の疑問は解決しました。どうもありがとうございました。

miyasiro 1998/01/17(土) 01:25:36
こちらも、いろいろ参考になりました。ありがとうございます。
> open(STDOUT,"|/usr/local/bin/nkf -j");
も機会があれば、使ってみます。

UNIXのシェルスクリプトを少し勉強しなければ…

[上に] [前に] [次に]