我有一个用Perl编写的IRC bot,使用已弃用的,未记录的和不受欢迎的Net :: IRC库。不过,它运行得很好......除非连接断开。看来图书馆在实施重新连接支持之前不再更新。显而易见的解决方案是重写整个机器人以利用库的后继者,但不幸的是,这需要重写整个机器人。
所以我对解决方法很感兴趣。
我当前的设置是supervisord配置为每当进程意外退出时重新启动僵尸程序,并且一个cron作业在互联网连接丢失时终止进程。
这不能像我希望的那样工作,因为僵尸程序似乎无法检测到由于互联网中断导致连接丢失。它会愉快地继续运行,什么都不做,假装仍然连接到IRC服务器。
我有以下代码作为主程序循环:
while (1) {
$irc->do_one_loop;
# can add stuff here
}
我希望它能做的是:
a)检测到互联网已经关闭,
b)等到互联网上升,
c)退出脚本,以便supervisord可以复活它。
还有其他更好的方法吗?
编辑:脚本方法不起作用,原因不明。我正在尝试制作一个单独的脚本来解决它。
#!/usr/bin/perl
use Net::Ping::External;
while (1) {
while (Net::Ping::External::ping(host => "8.8.8.8")) { sleep 5; }
sleep 5 until Net::Ping::External::ping(host => "8.8.8.8");
system("sudo kill `pgrep -f 'perl painbot.pl'`");
}
答案 0 :(得分:1)
假设do_one_loop
不会挂起(如果有的话,可能需要添加一些alarm
),您需要主动轮询某些内容以判断网络是否已启动。这样的事情应该在失败后每隔5秒进行一次ping,直到你得到响应,然后退出。
use Net::Ping::External;
sub connectionCheck {
return if Net::Ping::External::ping(host => "8.8.8.8");
sleep 5 until Net::Ping::External::ping(host => "8.8.8.8");
exit;
}
编辑:
由于do_one_loop
似乎确实挂起,因此您需要一些方法来绕过它。时间长短取决于您期望它运行的时间长度,以及如果它变得无法响应您愿意等待多长时间。一种简单的方法是使用alarm
(假设您不在Windows上):
local $SIG{'ALRM'} = sub { die "Timeout" };
alarm 30; # 30 seconds
eval {
$irc->do_one_loop;
alarm 0;
};
答案 1 :(得分:1)
Net::IRC
主循环支持超时和预定事件。
尝试这样的事情(我没有测试过,自从我上次使用模块已经7年了......):
# connect to IRC, add event handlers, etc.
$time_of_last_ping = $time_of_last_pong = time;
$irc->timeout(30);
# Can't handle PONG in Net::IRC (!), so handle "No origin specified" error
# (this may not work for you; you may rather do this some other way)
$conn->add_handler(409, sub { $time_of_last_pong = time });
while (1) {
$irc->do_one_loop;
# check internet connection: send PING to server
if ( time-$time_of_last_ping > 30 ) {
$conn->sl("PING"); # Should be "PING anything"
$time_of_last_ping = time;
}
break if time-$time_of_last_pong > 90;
}