Как лучше всего отправить электронное письмо, если в скрипте Perl возникает какая-либо ошибка? - PullRequest
2 голосов
/ 09 марта 2011

Я работаю над сценарием, который делает много вещей, и если в какой-то момент во время его выполнения исполняется 'die' или возникает ошибка, я хотел бы отправить мне сообщение электронной почты.

В настоящее время я использую блок END, чтобы проверить состояние выхода, и если оно больше 0, вызвать подпрограмму с сообщением об ошибке, но мне интересно, есть ли лучший способ.Недостаток этой текущей реализации заключается в том, что если в подпрограмме электронной почты произойдет ошибка, произойдет бесконечный цикл.

Ответы [ 4 ]

4 голосов
/ 09 марта 2011

У нас действительно есть два отдельных вопроса:

  1. Как (надежно) выполнить код, когда программа die s без создания бесконечного цикла, если этот код также попадетфатальная ошибка?

  2. Как лучше всего отправить письмо с кодом Perl?

Итак, ответить на каждый по отдельности:

  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!) И, при необходимости, обработка общих методов аутентификации на этом сервере.

3 голосов
/ 09 марта 2011

Я использую 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 голосов
/ 09 марта 2011

если вы работаете в системе Unix, включая (возможно) Mac OS / X: ./myscript.pl 2>/tmp/myscript.pl.log || mail -s 'myscript.pl failed' me@example.com < /tmp/myscript.pl.log

в Windows, я не знаю.

1 голос
/ 09 марта 2011

Мои личные предпочтения - это Perl-модуль Net :: SMTP. Несколько многословно, но очень полнофункционально.

 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...