另一个包中的 log4perl 运行 不触发通过电子邮件发送的消息

log4perl run from within another package not firing messages sent through email

我在使用 log4perl 通过电子邮件发送消息时看到无法解释的行为。

所以下面的测试脚本工作正常,邮件发送没有问题:

#!/usr/bin/perl
use strict;
use warnings;
use Log::Log4perl qw(:easy);
use Log::Dispatch;

my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    threshold => "INFO",
    to => 'myemail@mail.com',
    subject => 'Perl script message'
);

my $email_logger = get_logger();
$email_logger->level($INFO);
$email_logger->add_appender($appender_email);

$email_logger->info('hi');

Log::Dispatch::Email::SSMTP 是我编写的使用 ssmtp 命令发送电子邮件的模块。

当这个完全相同的代码被移动到与我的原始脚本位于同一目录的另一个文件中的另一个包时,奇怪的事情就开始了。当我这样做并从我的原始脚本中使用该包时,不会发送任何电子邮件,也不会抛出任何错误。

但是,如果我改变:

Log::Dispatch::Email::SSMTP

Log::Log4perl::Appender::Screen

当我 运行 我的脚本时,它会在屏幕上打印 "hi" 就好了。

那么,如果 log4perl 在将消息发送到屏幕时有效,为什么它在尝试发送电子邮件时不起作用?为什么相同的代码会从原始脚本中而不是从包中触发电子邮件?同样,没有抛出任何错误或任何出错的迹象。我已经验证我的模块加载了打印语句。所以我的模块代码确实正在加载,但电子邮件仍未触发。

更新 这是代码根据评论中的请求工作时的代码。

maillog.pl

#!/usr/bin/perl
BEGIN { unshift @INC, "/home/steve/perl/perl-lib" }
use strict;
use warnings;
use Testy;

print 'start' . "\n";

这是 Testy.pm 包:

package Testy;
BEGIN { unshift @INC, "/home/steve/perl/perl-lib" }
use strict;
use warnings;
use Log::Log4perl qw(:easy);
use Log::Dispatch;

print 'end' . "\n";
my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    #"Log::Log4perl::Appender::Screen",
    threshold => "INFO",
    to => 'myemail@mail.com',
    subject => 'Perl script message'
);

my $email_logger = get_logger();
$email_logger->level($INFO);
$email_logger->add_appender($appender_email);

$email_logger->info('hi');

1;

这是我的 SSMTP 模块,位于 /home/steve/perl/perl-lib/Log/Dispatch/Email/SSMTP:

package Log::Dispatch::Email::SSMTP;

use strict;
use warnings;
use Log::Dispatch::Email;
use Data::Dumper;

use base qw( Log::Dispatch::Email );
print "hi, i'm here!\n";

sub send_email {
  my $self = shift;
  my %p = @_; 
  my $to = escape ( join ',', @{$self->{to}} );
  my $subject = $self->{subject};
  my $message = $p{message};
  $message =~ s/'/'\''/g;
  print $to . "\n";
  print $subject . "\n";
  print $message . "\n";
  print "I'm working!";

  system("echo 'To: $to\nFrom: \'Me\' <myemail\@gmail.com>\nSubject:$subject\n\n$message' | /usr/sbin/ssmtp $to");
}

sub escape {
  my $address = shift;
  $address =~ s/@/\@/g;
  return $address;
}

1;

当我 运行 ./maillog.pl 使用 Testy 包中的代码时没有发送电子邮件(相同的代码在 maillog.pl 文件中工作。但是,如果我取消注释 Log::Dispatch::Email::SSMTP 并替换为 Log::Log4perl::Appender::Screen 它有效。

更新 #2 如果我将 Log::Log4perl::Appender::Screen 更改为 Log::Dispatch::Screen,它也会起作用。所以也许 Log::Dispatch::Email 中出现了某种错误?

click here

常见问题解答的帮助下找到了问题

显然,正在进行一些缓冲,因此在达到生成的消息数量的某个阈值之前,不会立即发送电子邮件。虽然对于为什么当代码在 main 包中时立即发送电子邮件对我来说仍然是个谜。

下面是将 buffered 属性 设置为 0 的代码:

my $appender_email = Log::Log4perl::Appender->new(
    "Log::Dispatch::Email::SSMTP",
    threshold => "INFO",
    to => 'me@mymail.com',
    buffered => 0,
    subject => 'Perl script message'
);