>その関数の中のdieを捕捉してエラーメッセージを$logfileに出力する、
>ということは可能なのでしょうか???
そのエラーメッセージを書き込むためのopen処理でまたエラーが出たら・・・
ってなると永遠に続きそうですね^^;
例えば以下のように、open処理を何回か繰り返して行い、ダメな場合はあきら
めるとかはいかかでしょうか?
my $try_count = 5;
my ($fh, $is_open);
for ( 1..$try_count ) {
$is_open = open my $fh, ">>", $logfile;
last if $is_open;
sleep 1;
}
if ( $is_open ) {
print {$fh} "$date:@_";
close $fh;
}
もっといい方法を誰かが提示してくれるかもしれません。
シグナルの無効化(デフォルト状態に戻す)は、以下でもいいようです。
(互換性からこちらのほうがいいのかしら)
$SIG{__DIE__} = 'DEFAULT';
ところで、以下のようにエラー処理をする関数を作るのではダメなのでしょうか?
sub error {
open my $fh, ">", "error.log";
print {$fh} @_;
close $fh;
die @_;
}
my $imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or error "Cannot connect to $hostname imap:143. $!";
質問者
お礼
ryu_chan様
早速の追加回答ありがとうございます!
教えていただいた方法をもとに検証してみたところ、
以下のスクリプトでdieの標準エラー出力を任意のファイルに出力できました!
####################################
my $logfile = "/var/log/imap4.log";
sub error {
my $date = localtime;
open my $fh, ">>", "$logfile";
print {$fh} "$date:@_";
close $fh;
die @_;
}
my $imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or error "Cannot connect to $hostname imap:143.$!\r\n";
$imap->logout();
exit
#####################################
ちなみに、errorという関数の中で、
$logfileがopenできなかったことを考慮してor die処理を入れたとした場合、
その関数の中のdieを捕捉してエラーメッセージを$logfileに出力する、ということは可能なのでしょうか???
その通りです。
dieを実行する前にシグナルを定義しておきます。
スコープを作って、dieを捕捉する範囲を限定するといいかもしれません。
{
local $SIG{__DIE__} = sub {
open my $fh, ">", "data.txt";
print {$fh} @_;
close $fh;
};
die "just die";
}
あるいは、捕捉すべきdieがなくなった段階でdeleteするとかでしょうか。
delete $SIG{__DIE__};
全体を eval ブロックで囲むと、die のエラーもトラップされて $@ にセットされると思います。
次は別の例ですが、(1) と (2) は同じエラーメッセージが表示されます。
(1)
open FH, "not_exist" or die "Can't open not_exist: $!";
(2)
eval {
open FH, "not_exist" or die "Can't open not_exist: $!";
};
if ($@) {
print $@;
exit;
}
質問者
お礼
kumoz様
ご回答ありがとうございます。
全体を eval ブロックで囲むという方法は、
ここに質問したあと私なりに色々調べて行き当たりました。
そして、以下のようなサンプルスクリプトを作成しましたところ、
期待とおりの結果がえられました。
##################################################
$logfile = "/var/log/imap4.log";
#my $imap;
#my $folders;
eval {
my $imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or die "1 \n";
my $folders = $imap->folders or die "2 \n";
$imap->logout();
# );
};
###### Error judgment #####
if ($@) {
open (FILE, ">>$logfile") or die "$!";
$data = localtime;
print FILE "$data FAILURE:$hostname port:143(imap4) failed. \n";
close (FILE);
} else {
open (FILE, ">>$logfile") or die "$!";
$data = localtime;
print FILE "$data SUCCESS:$hostname port:143(imap4) logged in. \n";
close (FILE);
}
exit
##################################################
スクリプトをご確認いただいて気になることがありましたら、
ご指摘いただけますと幸いです。
よろしくお願します。
お礼
ryu_chan様 貴重なご意見をたくさんありがとうございます。 今回はevalを用いて要件を実現することにしましたが、 サブルーチンでdieを捕捉するという手法(考え方)、 非常に勉強になりました。 ありがとうございました! これから検証して実際の動きをみながら作成したいと思います。