使用perl模块Log::Syslog::Fast-无法捕获异常

使用perl模块Log::Syslog::Fast-无法捕获异常,perl,exception,tcp,exception-handling,eval,Perl,Exception,Tcp,Exception Handling,Eval,我使用Log::Syslog::Fast将日志转发到Syslog服务器。我正在测试脚本,看看如果syslog服务器突然崩溃,它会有什么反应 为了进行测试,我创建了一个包含测试消息的文件,启动脚本&然后在syslog服务器上收到2条消息后关闭syslog服务器 脚本发送了第三条消息&然后消失。eval&使用警告“致命”=>“全部”未捕获终止”没有帮助 有人能帮我抓住这个例外并更优雅地关闭脚本吗 这里需要做的是-发送Command2后,脚本应该捕获异常并显示: Fail: Command3 代码提

我使用Log::Syslog::Fast将日志转发到Syslog服务器。我正在测试脚本,看看如果syslog服务器突然崩溃,它会有什么反应

为了进行测试,我创建了一个包含测试消息的文件,启动脚本&然后在syslog服务器上收到2条消息后关闭syslog服务器

脚本发送了第三条消息&然后消失。
eval
&
使用警告“致命”=>“全部”未捕获终止”没有帮助

有人能帮我抓住这个例外并更优雅地关闭脚本吗

这里需要做的是-发送Command2后,脚本应该捕获异常并显示:

Fail: Command3
代码提取:

$logger = Log::Syslog::Fast->new(LOG_TCP,$server, 514, 13, 6, "test_machine", "Syslog");
$logger->set_pid(0);

foreach $line(<SPOOL>)
{
        ($machine,$time,$message)=(split '\|',$line);
        eval{
                $logger->set_sender($machine);
                $logger->send($message,$time);
        };
        if($@)
        {
                print "\nFail: $message\n";
                exit;
        }
        else
        {
                print "\nSuccess: $message\n";
        }
        sleep 5;
}
test_machine1|1461201306|Command1
test_machine1|1461201311|Command2
test_machine1|1461203214|Command3
test_machine1|1461203219|Command4
test_machine2|1461204005|Command5
test_machine2|1461204006|Command6
test_machine2|1461204149|Command7
test_machine3|1461204154|Command8
test_machine3|1461206936|Command9
test_machine3|1461206942|Command10
Success: Command1

Success: Command2

Success: Command3
read(4, "test_machine1|1461201306|Command"..., 4096) = 341
read(4, "", 4096)                       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:06 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command1\n\n\n", 19Success Command1


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:11 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command2\n\n\n", 19Success Command2


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:46:54 test_machin"..., 59, 0, NULL, 0) = 59
输出:

$logger = Log::Syslog::Fast->new(LOG_TCP,$server, 514, 13, 6, "test_machine", "Syslog");
$logger->set_pid(0);

foreach $line(<SPOOL>)
{
        ($machine,$time,$message)=(split '\|',$line);
        eval{
                $logger->set_sender($machine);
                $logger->send($message,$time);
        };
        if($@)
        {
                print "\nFail: $message\n";
                exit;
        }
        else
        {
                print "\nSuccess: $message\n";
        }
        sleep 5;
}
test_machine1|1461201306|Command1
test_machine1|1461201311|Command2
test_machine1|1461203214|Command3
test_machine1|1461203219|Command4
test_machine2|1461204005|Command5
test_machine2|1461204006|Command6
test_machine2|1461204149|Command7
test_machine3|1461204154|Command8
test_machine3|1461206936|Command9
test_machine3|1461206942|Command10
Success: Command1

Success: Command2

Success: Command3
read(4, "test_machine1|1461201306|Command"..., 4096) = 341
read(4, "", 4096)                       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:06 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command1\n\n\n", 19Success Command1


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:11 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command2\n\n\n", 19Success Command2


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:46:54 test_machin"..., 59, 0, NULL, 0) = 59
战略输出:

$logger = Log::Syslog::Fast->new(LOG_TCP,$server, 514, 13, 6, "test_machine", "Syslog");
$logger->set_pid(0);

foreach $line(<SPOOL>)
{
        ($machine,$time,$message)=(split '\|',$line);
        eval{
                $logger->set_sender($machine);
                $logger->send($message,$time);
        };
        if($@)
        {
                print "\nFail: $message\n";
                exit;
        }
        else
        {
                print "\nSuccess: $message\n";
        }
        sleep 5;
}
test_machine1|1461201306|Command1
test_machine1|1461201311|Command2
test_machine1|1461203214|Command3
test_machine1|1461203219|Command4
test_machine2|1461204005|Command5
test_machine2|1461204006|Command6
test_machine2|1461204149|Command7
test_machine3|1461204154|Command8
test_machine3|1461206936|Command9
test_machine3|1461206942|Command10
Success: Command1

Success: Command2

Success: Command3
read(4, "test_machine1|1461201306|Command"..., 4096) = 341
read(4, "", 4096)                       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:06 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command1\n\n\n", 19Success Command1


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:15:11 test_machin"..., 59, 0, NULL, 0) = 59
write(1, "Success Command2\n\n\n", 19Success Command2


)  = 19
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({5, 0}, 0x7ffc707478f0)       = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0
sendto(3, "<110>Apr 20 21:46:54 test_machin"..., 59, 0, NULL, 0) = 59
读取(4,“测试机器1 | 1461201306 |命令”…,4096)=341
读(4,“,4096)=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
发送到(3,“Apr 20 21:15:06测试机器”…,59,0,NULL,0)=59
写入(1,“成功命令1\n\n”,19成功命令1
)  = 19
rt_sigprocmask(SIG_块,[CHLD],[8)=0
rt_sigaction(SIGCHLD,NULL,{SIG_DFL,[],0},8)=0
rt_sigprocmask(SIG_SETMASK,[],NULL,8)=0
纳米睡眠({5,0},0x7ffc707478f0)=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
发送到(3,“Apr 20 21:15:11测试机器”…,59,0,NULL,0)=59
写入(1,“成功命令2\n\n”,19成功命令2
)  = 19
rt_sigprocmask(SIG_块,[CHLD],[8)=0
rt_sigaction(SIGCHLD,NULL,{SIG_DFL,[],0},8)=0
rt_sigprocmask(SIG_SETMASK,[],NULL,8)=0
纳米睡眠({5,0},0x7ffc707478f0)=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
发送到(3,“Apr 20 21:46:54测试机器”…,59,0,NULL,0)=59
我希望脚本在尝试发送第三条消息时失败,但它没有

write(1,“成功命令3\n\n”,19成功命令3
)  = 19
rt_sigprocmask(SIG_块,[CHLD],[8)=0
rt_sigaction(SIGCHLD,NULL,{SIG_DFL,[],0},8)=0
rt_sigprocmask(SIG_SETMASK,[],NULL,8)=0
纳米睡眠({5,0},0x7ffc707478f0)=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
stat(“/etc/localtime”,{st_mode=S_IFREG | 0644,st_size=3519,…})=0
发送到(3,“Apr 20 21:46:59测试机器”…,59,0,空,0)=-1个EPIPE(断管)
---SIGPIPE{si_signo=SIGPIPE,si_code=si_USER,si_pid=26037,si_uid=3179}---
+++被SIGPIPE杀死+++

在尝试发送第四条消息时,脚本最终死亡。不幸的是,eval没有捕获异常。

您可能希望像这样捕获SIGPIPE:

$SIG{PIPE} = "IGNORE";
从:

如果您正在向管道写入数据,还应该捕获SIGPIPE。否则,想象一下当您启动一个到一个不存在的命令的管道时会发生什么:open()很可能会成功(它只反映fork()的成功),但是您的输出将失败——非常惊人。Perl无法知道该命令是否有效,因为您的命令实际上是在一个单独的进程中运行的,该进程的exec()可能已失败。因此,虽然伪命令的读取器只返回一个快速EOF,但伪命令的编写器将收到一个信号,他们最好准备好处理这个信号

另外,在C程序中写入断开的套接字时,请查看该命令。

尝试添加一行

$SIG{PIPE} = sub {
die "SIGPIPE";
};
在发送任何东西之前

您可能还想尝试“打印”而不是死亡

我希望脚本在尝试发送第三条消息时失败,但它没有

TL;DR由于TCP协议的工作方式,您不能这样做

客户端和服务器通过套接字进行通信。当客户端写入套接字时,实际上是在写入缓冲区;没有迹象表明消息是否已实际传递

客户机只能在某些数据实际发送到服务器后才知道连接已关闭,因此第一次写入缓冲区将成功

下面是正在发生的事情:

  • 当您关闭服务器时,它会发送一个TCP
    FIN
    数据包。
    FIN
    表示连接的一端完成了数据发送,但仍然可以接收;这并不表示连接已关闭

  • 客户端成功地将第三条日志消息写入套接字缓冲区,因此不会引发异常

  • 服务器发送一个TCP
    RST
    数据包,指示它不再侦听

  • 由于
    RST
    ,操作系统现在知道服务器端的TCP连接已关闭。当客户机尝试写入套接字缓冲区时,进程将收到
    SIGPIPE
    的信号,写入操作将返回
    EPIPE


  • 在尝试发送第四条消息时,脚本最终死亡。不幸的是,eval没有捕获异常

    您没有处理
    SIGPIPE
    ,因此当发出信号时,程序将终止。在脚本顶部附近添加以下内容以忽略
    SIGPIPE

    $SIG{PIPE} = 'IGNORE';
    
    现在,您可以随心所欲地处理
    send
    方法引发的异常


    进一步阅读:

    • 第2.22节,“我的申请何时收到SIGPPIPE?”

    在每种情况下(对于“如果”)您的$@值得到了什么?在第三条消息之后会发生什么?它是否继续无限期地报告成功,还是最终抛出异常?我想可能是相关的。对我来说很好。您是否尝试过strace以获取更多关于正在发生的事情的信息?当我尝试pri时,success&fail$@的故事是空的