首页 > 解决方案 > 使用 Mail::SpamAssassin::Client 时如何捕获连接错误

问题描述

我在 Perl 中创建对象时遇到错误。我当前代码的一部分是这样的:

#!/usr/bin/perl
use Mail::SpamAssassin::Client;
use warnings;
use strict;

my $client = new Mail::SpamAssassin::Client({port => 783, host => 'localhost'});
my $message = '';

if(!$result) {
    print "Cant process a message ! Error: " . $result;
}

因此,如果对象已正确创建,我无法检查 $client 变量。只有我在调用 $client->process($message) 方法后只能检查 $result 变量,但这对我来说并不令人满意。例如,如果 spammassassin 守护程序将离线,那么我在终端中进行了通信:

无法创建与 spamd 守护程序的连接:连接被拒绝

也许我可以在调用静态方法后捕获此错误消息或错误代码?

标签: perlobjectspamassassin

解决方案


该模块执行此操作:

unless ($remote) {
  print "Failed to create connection to spamd daemon: $!\n";
  return;
}

乌。模块不应该这样做。更糟糕的是,它写入 STDOUT 而不是 STDERR!

...实际上,它写入默认文件句柄,通常是STDOUT,但这可以使用select. 这为我们提供了一个解决方案。

use Scope::Guard qw( guard );

sub validate {
   my ($client) = @_;
   open(my $fh, ">", $^O eq 'Win32' ? 'nul' : '/dev/null')
      or die $!;

   my $old_fh = select($fh);
   my $guard = guard { select($old_fh); };
   return $client->ping();
}

my $rv = eval { validate($client) };
die($@) if $@;
die($!) if !$rv;

它执行 ping 请求并返回并检查响应。如果你想检查创建连接而不是别的,你可以使用

use Scope::Guard qw( guard );

sub validate {
   my ($client) = @_;
   open(my $fh, ">", $^O eq 'Win32' ? 'nul' : '/dev/null')
      or die $!;

   my $old_fh = select($fh);
   my $guard = guard { select($old_fh); };
   return !!$client->_create_connection();
}

validate($client)
   or die($!);

请注意,该模块会为每个方法调用创建一个新连接,因此检查可能会通过,但稍后的调用可能会失败(例如,由于网络问题)。


推荐阅读