【问题标题】:How to set up a internet connectivity detector for a Net::IRC bot?如何为 Net::IRC 机器人设置互联网连接检测器?
【发布时间】:2013-10-18 15:24:06
【问题描述】:

我有一个用 Perl 编写的 IRC 机器人,使用已弃用、未记录和不受欢迎的 Net::IRC 库。尽管如此,它运行得很好......除非连接断开。在他们实现对重新连接的支持之前,库似乎停止更新。显而易见的解决方案是重写整个机器人以利用库的继任者,但不幸的是,这需要重写整个机器人。

所以我对解决方法很感兴趣。

我当前的设置是 supervisord 配置为在进程意外退出时重新启动机器人,以及一个 cron 作业在 Internet 连接丢失时终止进程。

这并不像我希望的那样工作,因为机器人似乎无法检测到它由于互联网中断而失去连接。它会愉快地继续运行,什么也不做,假装仍然连接到 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'`");
}

【问题讨论】:

    标签: linux perl irc


    【解决方案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;
    };
    

    【讨论】:

    • do_one_loop 似乎挂起 - 我如何使用alarm 解除挂起?这不是我的功能之一,它来自图书馆。
    • 我已经尝试过了,就像pastie.org/8396134 一样,但没有成功。也许我可以把它放在一个单独的脚本中,而是通过系统调用杀死机器人?
    【解决方案2】:

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 2015-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多