いつもお世話になっております。
以下のようなスクリプトを書き、
imapサーバの死活監視を行おうと思っております。
#################################
my $imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or die "Cannot connect to $hostname imap:143. $!";
-------処理は続きますが割愛-------
#################################
そこで、1つ壁にぶつかったので質問いたしました。
+++壁の内容+++
imapサーバに何らかの理由で接続できなかったケースを考慮して、
die関数を使おうと思ったのですが、
このdie関数は、「引数に指定した値を標準エラー出力に出力」するとのことなのですが、
引数に指定した値を任意のファイルに出力する方法はないのでしょうか??
+++やりたいことの背景+++
imapサーバを監視するPerlスクリプトは、
実行するたびに指定したファイルに実行結果と実行時間を出力したい。
実行結果と実行時間を出力したファイルを
別の監視プログラムが監視するという二重構造の監視を行いたい。
imapサーバを監視するPerlスクリプトの実行結果を、
どうしても任意のファイルに出力したい。
+++++++++++++++++++++++++++++++++
以上です。
よろしくお願いします。
No.7ベストアンサー
- 回答日時:
すいません、No.6の記述に間違いを発見しました。
$is_open = open my $fh, ">>", $logfile;
↓ ↓訂正
$is_open = open $fh, ">>", $logfile;
ryu_chan様
貴重なご意見をたくさんありがとうございます。
今回はevalを用いて要件を実現することにしましたが、
サブルーチンでdieを捕捉するという手法(考え方)、
非常に勉強になりました。
ありがとうございました!
これから検証して実際の動きをみながら作成したいと思います。
No.8
- 回答日時:
> 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();
>
> # );
> };
No2 です。「全体を」と書いたので、誤解を与えたかもしれません。「質問に書かれていたコード全体」という
意味です。上のコードの場合、or die "1 \n"; の次の行で eval を終了する必要があります。new() に失敗した場合は、
次の2行の $imap->folders と $imap->logout() を実行してはならないからです。また、new() に失敗した場合の
エラー処理は、直後に行う必要があります。
my $imap;
eval {
$imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or die "1 \n";
};
if ($@) {
open (FILE, ">>$logfile") or die "$!";
$data = localtime;
print FILE "$data FAILURE:$hostname port:143(imap4) failed. \n";
close (FILE);
} else {
my $folders = $imap->folders or die "2 \n";
$imap->logout();
...
もう1つですが、die "1 \n" という書き方は、何ら有益な情報を含んでいず、あまり適切とはいえません。
失敗の原因や失敗した行番号が必要なければ、eval や die を使わずに unless ($imap) { エラー処理 }
とすることもできます。
kumoz様
「スクリプトををご確認いただいて気になることがありましたら・・・」
などと図々しく確認をお願いしてしまったにもかかわらず、
適切な回答アドバイスをいただきありがとうございます!
ご教示いただいたevalの使い方でこれから検証し、
より精度の高い監視スクリプトを作成したいと思います。
No.6
- 回答日時:
>その関数の中の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;
}
もっといい方法を誰かが提示してくれるかもしれません。
No.5
- 回答日時:
シグナルの無効化(デフォルト状態に戻す)は、以下でもいいようです。
(互換性からこちらのほうがいいのかしら)
$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に出力する、ということは可能なのでしょうか???
No.4
- 回答日時:
その通りです。
dieを実行する前にシグナルを定義しておきます。
スコープを作って、dieを捕捉する範囲を限定するといいかもしれません。
{
local $SIG{__DIE__} = sub {
open my $fh, ">", "data.txt";
print {$fh} @_;
close $fh;
};
die "just die";
}
あるいは、捕捉すべきdieがなくなった段階でdeleteするとかでしょうか。
delete $SIG{__DIE__};
No.3
- 回答日時:
__DIE__擬似シグナルを用いて、dieをトラップするのはどうでしょうか?
$SIG{__DIE__} = sub {
open my $fh, ">", "error.log";
print {$fh} @_;
close $fh;
};
ryu_chan様
回答ありがとうございます。
教えて頂いた方法について
私の認識に間違いがないか確認させてください。
◆私の認識
dieのシグナルに反応しさらにその実行結果をファイルに保存する、
という関数を用意し、スクリプト内のdieが実行される前の部分に配置しておく
という理解で間違いないでしょうか。
よろしくお願します。
No.2
- 回答日時:
全体を 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
##################################################
スクリプトをご確認いただいて気になることがありましたら、
ご指摘いただけますと幸いです。
よろしくお願します。
No.1
- 回答日時:
やったことはないけど
open(STDERR, ">/some/path/to/file");
みたいなことはできないかなぁ. 必要ならバッファリングも何とかする.
Tacosan様
ご回答ありがごとうございます。
open(STDERR, ">/some/path/to/file");
という方法で私のやりたいことを試すとした場合、
細かい話で恐縮ですが、
以下のようなスクリプトですと、
my $imap = Mail::IMAPClient->new(
Server => $hostname,
User => $username,
Password => $password,
Timeout => 5,
) or die "Cannot connect to $hostname imap:143. $!";
どの部分に挿入したらよいのでしょうか。
Perl初学者のため、基本的なことに対する理解が浅いため、
質問させていただきました。
お手数おかけしますが、ご教示いただきますと幸いです。
よろしくお願します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) bashのgrepで複数の検索、かつスクリプト内で改行する方法を教えてください。 1 2022/10/06 20:09
- オープンソース gmailでのimap設定 1 2022/09/15 13:25
- PHP phpの imap_search で漢字コード 1 2022/09/06 17:32
- その他(開発・運用・管理) Windowsバッチファイルでリモートデスクトップを自動ログインするが確認画面が出る対処方法 1 2022/12/19 15:48
- その他(プログラミング・Web制作) Linuxについて質問です。 引数に指定されたアクセスログのファイルからアクセス数が多い順に上位3つ 1 2023/02/03 03:46
- Java java 次の機能を有するメソッドを自クラスに作成し、実装したいです。 機能 名前判定機能 →名前が 3 2022/06/16 16:08
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
- C言語・C++・C# C言語 3 2022/10/04 15:07
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・「黒歴史」教えて下さい
- ・2024年においていきたいもの
- ・我が家のお雑煮スタイル、教えて下さい
- ・店員も客も斜め上を行くデパートの福袋
- ・食べられるかと思ったけど…ダメでした
- ・【大喜利】【投稿~12/28】こんなおせち料理は嫌だ
- ・前回の年越しの瞬間、何してた?
- ・【お題】マッチョ習字
- ・モテ期を経験した方いらっしゃいますか?
- ・一番最初にネットにつないだのはいつ?
- ・好きな人を振り向かせるためにしたこと
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
パイプをopenして/usr/bin/grep...
-
改行コードが勝手に
-
Perl で syntax error
-
close()で例外が投げられる理由
-
VBAでCSVファイルを途中行まで...
-
JavaでCSVファイルを高速に読む...
-
VBAでCSVファイルの特定行を書...
-
ExcelをCSV書き出す場合のシー...
-
全角と半角文字が混在している...
-
エクセルVBA コードが同じでも...
-
重複するデータを抽出できる秀...
-
2つのCSVファイルをマッチング
-
vba dir の相対パス
-
readdir()で得られるファイル・...
-
openした後、closeしないでプロ...
-
python renameについて
-
awkスクリプトでダブルクォーテ...
-
DOSコマンドで、標準出力を出力...
-
正規表現で、特定のファイル名...
-
batファイルでrenameができませ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
close()で例外が投げられる理由
-
where can I buy snowbord in t...
-
改行コードが勝手に
-
テキストファイルの本文中に行...
-
ファイル作成時
-
open中のファイルをrename
-
アルゴリズム java お店の営業...
-
perlのflock関数でロックをかけ...
-
Perl で syntax error
-
Perl 指定行への書き込み
-
perlで複数のファイルの処理に...
-
PICでFatFsでオープンした内容...
-
パスワードを外部ファイルから...
-
AutoCADのスクリプト
-
perlで大容量CSVのsort方法につ...
-
クリックを何回もされて、重複...
-
die関数のエラー出力先について
-
perlでファイル内の文字列を置...
-
巨大ファイルの行をを逆順に並...
-
Net-Snmpのtraphandleよりshell...
おすすめ情報