如果Perl脚本中发生任何错误,发送电子邮件的最佳方式是什么?

时间:2011-03-09 00:39:57

标签: perl

我正在编写一个执行许多操作的脚本,如果在执行期间的任何时候执行'die'或发生错误,我想向自己发送一封电子邮件。

我目前正在使用END块来检查退出状态,如果它大于0则调用错误电子邮件子程序,但我想知道是否有更好的方法。这个当前实现的缺陷是,如果在电子邮件子例程中发生错误,将发生无限循环。

4 个答案:

答案 0 :(得分:4)

我们在这里确实有两个不同的问题:

  1. 如果程序die没有创建无限循环,如果此代码也遇到致命错误,您如何(可靠地)执行代码?

  2. 从Perl代码发送电子邮件的最佳方式是什么?

  3. 所以,分别回答:

    1. 我会使用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";
      }
      
    2. 当然,CPAN上有很多优秀的邮件发送模块。我个人的偏好是MIME::Lite,默认情况下会使用sendmail发送邮件,但是,如果您使用的是Windows或其他没有sendmail命令的系统,则可以使用MIME::Lite->send("smtp");直接通过SMTP发送,无需通过本地MTA。还支持通过外发邮件服务器路由邮件(如果您的上游提供程序阻止端口25,则很方便!)并在需要时在该服务器上处理常见的身份验证方法。

答案 1 :(得分:3)

我将eval与sendmail一起使用(因为它几乎总是安装):

eval
{
    # do something
};
if ( $@ )
{

    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

$@

$ip
EOF

    close ( SENDMAIL )
        or warn "Sendmail didn't close nicely";

};

这将修复您的无限循环,但不会在电子邮件块首先死亡的情况下发送电子邮件。我认为@jcomeau_ictx获得了防弹奖。

我也不知道如何在Windows中执行此操作。希望这有帮助!

答案 2 :(得分:2)

如果您使用的是Unix系统,包括(可能)Mac OS / X:./myscript.pl 2>/tmp/myscript.pl.log || mail -s 'myscript.pl failed' me@example.com < /tmp/myscript.pl.log

Windows上的

我不知道。

答案 3 :(得分:1)

我的个人偏好是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();