使用perl模块Log::Syslog::Fast-无法捕获异常
我使用Log::Syslog::Fast将日志转发到Syslog服务器。我正在测试脚本,看看如果syslog服务器突然崩溃,它会有什么反应 为了进行测试,我创建了一个包含测试消息的文件,启动脚本&然后在syslog服务器上收到2条消息后关闭syslog服务器 脚本发送了第三条消息&然后消失。使用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 代码提
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协议的工作方式,您不能这样做
客户端和服务器通过套接字进行通信。当客户端写入套接字时,实际上是在写入缓冲区;没有迹象表明消息是否已实际传递
客户机只能在某些数据实际发送到服务器后才知道连接已关闭,因此第一次写入缓冲区将成功
下面是正在发生的事情:
当您关闭服务器时,它会发送一个TCPFIN
数据包。FIN
表示连接的一端完成了数据发送,但仍然可以接收;这并不表示连接已关闭
客户端成功地将第三条日志消息写入套接字缓冲区,因此不会引发异常
服务器发送一个TCPRST
数据包,指示它不再侦听
由于RST
,操作系统现在知道服务器端的TCP连接已关闭。当客户机尝试写入套接字缓冲区时,进程将收到SIGPIPE
的信号,写入操作将返回EPIPE
在尝试发送第四条消息时,脚本最终死亡。不幸的是,eval没有捕获异常
您没有处理SIGPIPE
,因此当发出信号时,程序将终止。在脚本顶部附近添加以下内容以忽略SIGPIPE
:
$SIG{PIPE} = 'IGNORE';
现在,您可以随心所欲地处理send
方法引发的异常
进一步阅读:
- 第2.22节,“我的申请何时收到SIGPPIPE?”
在每种情况下(对于“如果”)您的$@值得到了什么?在第三条消息之后会发生什么?它是否继续无限期地报告成功,还是最终抛出异常?我想可能是相关的。对我来说很好。您是否尝试过strace以获取更多关于正在发生的事情的信息?当我尝试pri时,success&fail$@的故事是空的