我正在處理一個執行很多事情的腳本,並且如果在執行過程中的任何時刻執行了「死亡」或發生了錯誤,我想向自己發送一封電子郵件。如果在Perl腳本中發生錯誤,發送電子郵件的最佳方式是什麼?
我正在使用END塊來檢查退出狀態,如果它大於0,則調用一個錯誤的電子郵件子例程,但我想知道是否有更好的方法。這種當前實現的缺陷是,如果在電子郵件子例程中發生錯誤,將會發生無限循環。
我正在處理一個執行很多事情的腳本,並且如果在執行過程中的任何時刻執行了「死亡」或發生了錯誤,我想向自己發送一封電子郵件。如果在Perl腳本中發生錯誤,發送電子郵件的最佳方式是什麼?
我正在使用END塊來檢查退出狀態,如果它大於0,則調用一個錯誤的電子郵件子例程,但我想知道是否有更好的方法。這種當前實現的缺陷是,如果在電子郵件子例程中發生錯誤,將會發生無限循環。
我用eval
和sendmail(因爲它幾乎總是安裝):
eval
{
# do something
};
if ([email protected])
{
my $ip = `ifconfig`
or die "Can't ifconfig: $!\n";
my @now = localtime;
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1], $now[0]);
open (SENDMAIL, "|/usr/sbin/sendmail -oi -t -fyou\@yourdomain.com")
or die "Can't fork for sendmail: $!\n";
print SENDMAIL << "EOF";
To: Your Name <you\@yourdomain.com>
Subject: ERROR: Exception
$now
[email protected]
$ip
EOF
close (SENDMAIL)
or warn "Sendmail didn't close nicely";
};
這將解決您的無限循環,但不會在萬一發送一封電子郵件,該郵件塊模具第一。我認爲@jcomeau_ictx獲得了防彈獎。
我也不知道如何在Windows中做到這一點。希望這可以幫助!
如果你是一個Unix系統中,包括(可能)的Mac OS/X上:./myscript.pl 2>/tmp/myscript.pl.log || mail -s 'myscript.pl failed' [email protected] < /tmp/myscript.pl.log
在Windows上,我不知道。
+1爲魯棒性! – mattexx 2011-03-09 00:59:00
我們真的來到這裏兩個獨立的問題:
你如何(可靠)執行代碼時,程序die
•不用創建一個無限循環,如果這個代碼也命中一個致命的錯誤?
從Perl代碼發送電子郵件的最佳方式是什麼?
所以,單獨回答每個:
不是一個END
塊,我會用一個$SIG{__DIE__}
處理器(未測試的代碼,但應該是正確的):
$SIG{__DIE__} = \&error_handler;
sub error_handler {
die @_ if $^S; # Do nothing if we died in an eval{}
delete $SIG{__DIE__}; # Clear handler in case following code also dies
print STDERR "Blue Wizard is about to die!\n";
}
當然,CPAN上有許多優秀的郵件發送模塊。我從他們中間個人的偏好是MIME::Lite,這將使用由默認sendmail
郵件,但是,如果你使用的是Windows或沒有sendmail
命令一些其他的系統,你可以使用MIME::Lite->send("smtp");
通過SMTP發送的情況下直接通過本地MTA會。還支持通過發送郵件服務器路由郵件(如果您的上游提供商阻止端口25,則方便!),並在需要時處理該服務器上的通用身份驗證方法。
我個人的偏好是Net :: SMTP perl模塊。有點冗長但非常全面。
my $mail = Net::SMTP->new($smtp_host);
$mail->mail("$login\@foo.com");
$mail->to("$login\@foo.com");
$mail->data();
#Generate email headers
$mail->datasend("From: Root <root\@foo.com>");
$mail->datasend("Subject: Status");
$mail->datasend("To: root\@foo.com");
$mail->datasend("\n") # Need one newline between headers and body
# Report data
$mail->datasend("Mail body here");
$mail->datasend("More mail body, repeat $mail->datasend() as needed");
# Then close connection
$mail->quit();
這兩種方法都很好。我喜歡這個更多的是因爲它適用於Windows,如果我取代Sendmail和我能夠做到這一點是在Perl。謝謝! – Matthew 2011-03-09 01:29:04