• ベストアンサー

dieやPerl自体でエラーが発生したときに、独自のルーチンを呼び出す方法

WindowsのActivePerl5.6を使っています。dieやdieやPerl自体でエラーが発生したときに、通常なら標準エラーに出力して、abortされるが、標準エラーを出力する前に独自の関数を実行させて終わらせることは可能でしょうか? 例えば、以下は可能でしょうか? sub myerror{ print "フック?\n"; goto MyJump; } print "TEST1\n"; die "これを表示させずに、別の処理(フックする方法)" ; # 標準エラーが出力されて終わる。 MyJump: print "TEST2 ここまで表示\n"; Linuxならできるのでしょうか?

  • Perl
  • 回答数4
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.4

> やはり、Windows環境ではwhile(1){}のループをCTRL+Cで止めた場合はは補足できないのですね。 WindowsでPerlを使う機会があまりないので詳しく調べたことがなかったのですが、ちょっと試してみたところ、手元の環境では Ctrl+C は捕捉できるようです。 - Windows 98/XP - Perl 5.8.0 # Ctrl+C 用のシグナルハンドラを定義 $SIG{INT} = sub {   print "SIG_INT\n";   $loop = 0; }; $loop = 1; while ($loop) {   print "*\n";   sleep 1; } > 良くあるPerlのDBIで返すエラーなどは補足ができるのでしょうか? これは eval で捕捉可能です。 詳しくはこちらをご覧ください。 http://member.nifty.ne.jp/hippo2000/perltips/dbimemo.htm#item_RaiseError http://member.nifty.ne.jp/hippo2000/perltips/dbimemo.htm#transactions > Windows上で補足できなくて困る割り込みはソフトウェア割り込み以外のハードウェア割り込み?っていうことでしょうか? 試しに他のプロセスから SIG_TERM を送ってみたところ、捕捉されずに終了してしまいました。捕捉できるかどうかは、割り込みの発生源には関係ないようです。どちらにしても不便なことに変わりありませんが。

その他の回答 (3)

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.3

die を捕捉して終了処理をフックするには、$SIG{__DIE__} を利用します。 プログラムの先頭などで   $SIG{__DIE__} = \&myerror; としておけば、die で死ぬ前に myerror が実行されます。 myerror には die のパラメータが引数として渡され、実行後は通常通り、STDERR へのメッセージ出力とともにプログラムが終了します。 また、myerror による共通の例外処理以外に、die のケースごとにカスタマイズされた例外処理を行いたい場合は、evalブロックを併用します。 例: # 共通の例外処理 sub myerror{   print "myerror: @_"; } $SIG{__DIE__} = \&myerror; eval {   die "Dying message\n";   print "このprint文は実行されません。"; }; # このevalブロック専用の例外処理 if ($@) {   print "exception: $@";   exit;  # exitしなければ、その後の処理を継続できます。 } # 実行結果 myerror: Dying message exception: Dying message ※evalブロック内で die すると、die のパラメータが $@ に設定されてブロックを抜けます。プログラムは終了されず、STDERR へのメッセージ出力もありません。 ※$SIG{__DIE__} も evalブロックも、プラットフォームに依らず利用できます。 なお、No.1 で特殊サブルーチン END を使った方法が紹介されていますが、END はプログラム終了時に必ず実行されてしまうので、die に限定した処理を行うことはできません。

kounesi
質問者

お礼

ありがとうございます。 やはり、Windows環境ではwhile(1){}のループをCTRL+Cで止めた場合はは補足できないのですね。 良くあるPerlのDBIで返すエラーなどは補足ができるのでしょうか? Windows上で補足できなくて困る割り込みはソフトウェア割り込み以外のハードウェア割り込み?っていうことでしょうか?無知ですみません。

  • root139
  • ベストアンサー率60% (488/809)
回答No.2

evalを使った例外処理の方法もあります。 Javaのtry/catchの様な感じです。 例)------------------------------------------- eval { print "TEST1\n"; die; }; if ($@) { # エラーが発生したときの処理 print "TEST2 ここまで表示\n"; exit(); } ---------------------------------------------- evalのブロックの中で例外が発生した場合、ブロック中のコードの実行は終了し、$@にエラーメッセージが設定されます。ただし、シグナルやパニックの様なエラーは捕捉出来ないようです。 evalの引数にはブロックと文字列が取れますが、文字列形式ではevalを実行するたびにコンパイルが行われて負荷が高くなるので、出来るだけブロック形式をとったほうが良いでしょう。

  • Ethersky
  • ベストアンサー率71% (168/235)
回答No.1

・die、例外発生等でインタプリタが終了するとき(シグナルによる終了は除く) END { 実行させたい内容 } ・シグナルによる終了時(Unix系列のみ) $SIG{HUP} = $SIG{INT} = $SIG{PIPE} = $SIG{QUIT} = $SIG{TERM} = \&signal_end; sub signal_end { 実行させたい内容 }

関連するQ&A

  • open (FILEHANDLE,"< $filename") or die "エラーメッセージ";について

    下記プログラムでperl_read_writes.txtを出力すると、中身が表示されるのですが、a_perl_read_writes.txt等に名前を変更すると、当然エラーが起きます。 が、die "$filenameを開けません。";の部分の $filenameを開けません。という文章が出力されないのですが、どなたか原因分かりませんか? ================================================== #!/usr/bin/perl print "Content-type: text/html;charset=Shift-JIS", "\n\n"; # HTMLの出力 print "<html>\n"; print "<body>\n"; print "ファイルの読み書き<br>\n"; $filename='/usr/local/apache/htdocs/aaa/bbb/perl_read_writes.txt'; # ファイルオープン open (FILEHANDLE,"< $filename") or die "$filenameを開けません。"; ...以下省略 ================================================== よろしくお願いします。

    • ベストアンサー
    • Perl
  • perlなんですが、403エラーについて

    サーバーとperlはつい最近はじめた初心者です。 カテゴリーをどちらにしようか悩みましたが、いろいろを試した結果 こちらに質問することにしました。もしかしたらperlの設定かもしれません。もしも間違っていたら申し訳ございません。 サーバーの種類はCentOS Linux 5 バージョン 1.390です。 バーチャルドメインで3つのドメインを管理しています。 一応以下のように仮定させてもらいます。 AAA.com BBB.com CCC.com 末行に書いたテスト用(test.cgi)をBBB.comのディレクトリーに アップしたところ、403エラーになりました。 パーミッションエラーかなと思い、パーミッションの設定をすべて 行いましたが解決できませんでした。 実際にAAA.comでは普通に稼動しているはずなのに、おかしいな~と 思って、その同じスクリプトをBBB.comにアップしたところ、 きちんと表示されました。 そこで、AAA.comの設定をhttp.confからすべて外してBBB.comのtest.cgi を確認したところ、表示されました。 もしかしたら、複数のドメインでperlを使う場合には、 なにか設定を行う必要があるのでしょうか? バーチャルドメインで設定している内容は以下のとおりです。 ※勝手にリンクマークされるのでwww は xxx に置き換えました。 <VirtualHost ***.***.***.***> DocumentRoot /var/xxx/AAA-com ServerName AAA.com HostNameLookups off UseCanonicalName on ScriptAlias /cgi-bin/ /var/xxx/AAA-com/cgi-bin/ <Directory /var/xxx/AAA-com/cgi-bin/> AllowOverride None Options ExecCGI Order allow,deny Allow from all </Directory> </VirtualHost> <VirtualHost ***.***.***.***> DocumentRoot /var/xxx/BBB-com ServerName AAA.com HostNameLookups off UseCanonicalName on ScriptAlias /cgi-bin/ /var/xxx/BBB-com/cgi-bin/ <Directory /var/xxx/BBB-com/cgi-bin/> AllowOverride None Options ExecCGI Order allow,deny Allow from all </Directory> </VirtualHost> テスト用のスクリプトは以下のとおりです。 #!/usr/bin/perl print "Content-type: text/html\n\n"; print "<html><head><title>CGI-Perl TEST</title>\n"; print "<meta http-equiv='content-type' content='text/html; charset=shift_jis'>\n"; print "</head><body><h2>CGI-Perlテスト</h2>\n"; print "</body></html>\n"; exit;

  • htmlからテキストを返すperlを実行する方法

    アクセスカウンターの数字画像を出力するperlのcgiを、<img>タグで、 <img src="./counter.cgi"> と、呼び出す方法があると思いますが、これと同じように、画像ではなくテキストを出力するperlのcgiをhtml中に呼び出して、ブラウザに表示する方法はないでしょうか? 以下のような感じかと漠然と思ったのですが、やはり上手くいくはずはありませんでした。 ■cgiプログラム(test.cgi) #!/usr/bin/perl print "Content-type: text/plain\n\n"; print "TEST TEXT"; exit 0; ■htmlファイル <html><head></head> <body> <br> <hr> <object data="./test.cgi" type="text/plain"></object> <hr> </body> </html> perlもhtmlも独学で学んだ基礎レベルだと自分で思っています。 どなたか突破口となるヒントをお願いします。

    • ベストアンサー
    • Perl
  • perl ハッシュ エラー

    現在perlの勉強中で、ハッシュの項目まできました。しかし、use strictにするとこのコードがエラーになります。 #!/usr/bin/perl use strict; use warnings; print "Content-type:text/html\n\n"; $hoge{"key1"} = "value1"; print $hoge{"key1"}; exit; ヴァージョンは5.8.9です。use strictをコメントアウトすればエラーはでません。どうしてエラーになってしまうのでしょうか?どうすればエラーを出さずに表示することができるのでしょうか?どうかご教授ください。よろしくお願いします。

    • ベストアンサー
    • Perl
  • perl use strict エラーにならない?

    perlの使い方を勉強しているのですが use strict;を記述すると 変数宣言が必要になるということですが 以下のように記述してもエラーになりません。 use strict;を記述すると my $a;がないと$a="Hello";で エラーになるのではないのでしょうか。 ---test.pl---- use strict; $a="Hello"; print $a; -------------- >test.pl Hello > (Windows7, ActivePerl)

    • ベストアンサー
    • Perl
  • PerlでHTTPヘッダの\nを外すとエラー

    【PerlでHTTPヘッダの最後の\nを1つでも外すとエラーになります】 初歩的なことですみません。 HTTPヘッダーの最後の\n\nなんですが、ヘッダーの文字列の後に改行が2つ?? と思って この\nを外して、 print "content-type:text/html;charset=utf-8"; とすると、「500 Internal Server Error」 print "content-type:text/html;charset=utf-8\n"; と\nが1つでも 「500 Internal Server Error」 となります。 「\n\n」と2つあればエラーにはならないんですが、なぜ必ず2つ必要なのでしょうか?これは改行が2つって意味ですかね? print "<html>\n"などの\nはソース上やコンソール出力結果上での改行なのはわかります。 この\nは改行したくなければ書かなくてもエラーになりませんよね。(当たり前ですが・・ #!/usr/bin/perl print "content-type:text/html;charset=utf-8\n\n"; ←HTTPヘッダーの\n\n print "<html>\n"; print "<body>\n"; print "<p>テキスト</p>\n"; print "</body>\n"; print "</html>\n";

    • ベストアンサー
    • Perl
  • perlの ¥033 不具合エラー

    以下のスクリプトを実行すると"Unrecognized character \033 at ./tools/aaa.pl line 5."というエラーが出てしまいます。やりたいことは 文中の "//! aaa"を全て削除して出力するというものです。何が悪いのでしょうか? ----------------- #! /usr/bin/perl while(<>){ if(m#//\s*\!.*#){ $_ =~ s#//\s*\!.*\n##; print "AAA: $_\n"; }else{ print $_; } } -------------- 以上、宜しくお願い致します。

  • Linux上でtcpdumpの出力をperlで処理したいと考えています

    Linux上でtcpdumpの出力をperlで処理したいと考えています。 下記のようにtcpdumpの標準出力をperlの標準入力で受け取ろうとしても tcpdumpの処理が終わらないためパイプ(|)経由でperlにデータが渡ってきません。 [test.pl] $|=1; foreach(<>){ print "--- $_"; } exit; Linux上のコマンド tcpdump -l | ./test.pl これをteeに置き換えるとtcpdumpの出力はリアルタイムに表示されます。 tcpdump -l | tee a.log 質問:perlでteeを作ることはできますか?

    • ベストアンサー
    • Perl
  • 標準出力と標準エラー出力を時系列にファイルへ

    例として、perlなどで、(test.plとします)  print "stdout1\n";  print STDERR "STDERR1\n";  print "stdout2\n";  print STDERR "STDERR2\n";  print "stdout3\n";  print STDERR "STDERR3\n"; このように、標準出力と、標準エラー出力が混在した状態の処理があった場合、 コマンドプロンプト(Windows2000)にて、 C:\>test.pl とすると、 stdout1 STDERR1 stdout2 STDERR2 stdout3 STDERR3 のように時系列に出力されますが、これをログファイルに取ろうとして、 C:\>test.pl 1>log.txt 2>&1 とすると、 C:\>cat log.txt STDERR1 STDERR2 STDERR3 stdout1 stdout2 stdout3 のように、標準エラー出力が先に吐き出されてしまいます。 これを画面出力時と同様に時系列で取れるようにしたいのですが、どのようにすれば良いでしょうか? 単純なことで困っています。よろしくお願いします。

  • ファイルの3行目までを出力したい

    Perl初心者です。 test.txtというファイルがあって、その中の1行目から3行目までを 出力したい場合はどうしたらいいでしょうか? open(FILE,"test.txt") || die "Open Error.\n"; @data = <FILE>; close(FILE); foreach (@data) { print $_; } これだと、ファイルの中身が全て出力されてしまいます。

    • ベストアンサー
    • Perl

専門家に質問してみよう