如何为Net :: IRC bot设置互联网连接检测器?

时间:2013-10-10 18:05:55

标签: linux perl irc

我有一个用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'`");
}

2 个答案:

答案 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;
}
相关问题