与ISP交流(他们很棒,我没有抱怨),他们想知道通常,连接断开了,我不敢轻易说...所以我写了一个脚本来监视...。
它所做的所有事情都是每秒对ADSL线路的远端进行一次ping(网关)。这只是一小步,并且影响不大。
这是我编写的脚本,基于此,我能够解决问题,并将相关邮件复制到ISP,并且他们能够将问题与某个地方的问题相关联...最终我替换了我的ADSL调制解调器,问题得以解决。
长话大说,有些短代码,但这是经典的perl hack ...
我的perl有点过时,因此我正在寻找有关如何使自己的用法现代化的想法,以及其他任何提示和技巧。
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use Net::Ping;
use Mail::Sendmail;
$| = 1;
my $defaultmail = 'rolfl@xxx.yyy';
my $defaultip = "8.8.8.8"; # Google's nameserver...
my $host = shift @ARGV;
$host ||= $defaultip;
my $mailto = shift @ARGV;
$mailto ||= $defaultmail;
sub mail {
my $subj = shift;
my $msg = scalar(localtime) . " -> " . $subj;
my %mail;
%mail = (smtp => 'localhost:25',
To => $mailto,
From => ,$mailto,
'X-InternetUp' => "q4312078q",
Subject => $subj,
Message => $msg);
sendmail(%mail) or die;
}
my $ping = Net::Ping->new();
my $up = 0; # start with it down, and it sends an 'up mail'.
my $start = time();
mail ("Starting network monitor");
while (1) {
sleep 1;
if ($ping->ping($host)) {
if (!$up) {
my $interval = time() - $start;
$start += $interval;
mail(sprintf("INTERNET -> JUST COME BACK - Was DOWN for %d seconds\n", $interval));
}
$up = 1;
} else {
if ($up) {
my $interval = time() - $start;
$start += $interval;
mail(sprintf("INTERNET -> JUST GONE DOWN - Was UP for %d seconds\n", $interval));
}
$up = 0;
}
}
该脚本留下类似的邮件:
Subject: INTERNET -> JUST GONE DOWN - Was UP for 65174 seconds
X-Internetup: ./netup
Date: Thu, 23 Oct 2014 14:07:23 -0400
To: rolfl@....
Content-Transfer-Encoding: quoted-printable
From: rolfl@...
Message-Id: <20141023180723.85C01440E60@mail....>
Thu Oct 23 14:07:23 2014 -> INTERNET -> JUST GONE DOWN - Was UP for 65174 s=
econds
#1 楼
参数处理$defaultmail
和$defaultip
的命名不正确-命名不一致:$host ||= $defaultip;
…
$mailto ||= $defaultmail;
我会还建议不要完全引入
$defaultmail
和$defaultip
作为变量。要么直接将它们写在my $host = (shift @ARGV) || '8.8.8.8'; # Google's nameserver
my $mailto = (shift @ARGV) || 'rolfl@example.com'; # RFC 2606
,要么定义一个常数:
use constant DEFAULTS => {
host => '8.8.8.8', # Google's nameserver
mailto => 'rolfl@example.com',
};
my $host = (shift @ARGV) // DEFAULTS->{host};
my $mailto = (shift @ARGV) // DEFAULTS->{mailto};
这里,我使用Perl 5.10中引入的逻辑定义或运算符
//
对事物进行了现代化。这样就可以将像'0'
之类的虚假字符串视为有效参数。理想情况下,
mail
子例程不应是捕获$mailto
值的闭包。我想这样的草率对于像这样的快速入侵是可以接受的。邮件
我认为邮件是一种有趣的记录工具。如果您的Internet连接断开,则该消息只会在本地MTA的队列中停留一段时间。附加到文本文件将起作用,并且结果将更易于分析。
为了便于分析,我建议使用基于ISO 8601的时间戳格式。
%mail
的值分配给From
时有一个逗号。我对该脚本仍然有效感到惊讶。它只是表明“只有perl
可以解析Perl”。虽然可以定义您想要的名称以
X-…
开头的任何邮件头,但是X-Mailer
头是事实上的标准已经适用。我不会麻烦地将
%mail
定义为变量。只需直接调用sendmail
,并使它们看起来像命名参数即可。Ping
Net::Ping
默认使用TCP回显协议,该协议很少受支持。 Google的8.8.8.8 DNS服务器肯定不支持它,因此您的默认设置不起作用。您可以使用ICMP探针,但是在Unix上需要root特权。
对8.8.8.8:53的TCP探针(TCP上的DNS)似乎有效。期望您的ISP的名称服务器能够通过TCP响应DNS,这也是合理的。 (否则,您的Internet服务实际上将一直处于关闭状态。)
循环
我不是
while (1) { sleep 1; … }
循环的粉丝。我建议将其编写为do { … } while sleep 1;
。两个分支中有一些重复的代码。我认为您已将条件写得不太理想。您真正想要的是对状态转换进行操作,所以要这样写。
建议的实现
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use Mail::Sendmail;
use Net::Ping;
use POSIX qw(strftime);
use constant DEFAULTS => {
host => '8.8.8.8', # Google's nameserver
mailto => 'rolfl@example.com',
};
my $host = (shift @ARGV) // DEFAULTS->{host};
my $mailto = (shift @ARGV) // DEFAULTS->{mailto};
sub mail {
my $subj = shift;
my $msg = strftime('%FT%T', localtime) . " -> " . $subj;
sendmail(smtp => 'localhost:25',
To => $mailto,
From => $mailto,
'X-Mailer' => "InternetUp q4312078q",
Subject => $subj,
Message => $msg) or die;
}
# $| = 1; # <-- The script prints nothing to STDOUT. This is pointless.
my $ping = Net::Ping->new('tcp');
$ping->port_number(getservbyname('domain', 'tcp'));
my $up = 0; # start with it down, and it sends an 'up mail'.
my $start = time;
mail("Starting network monitor");
do {
my $ping_ok = $ping->ping($host);
if ($ping_ok != $up) {
$up = $ping_ok;
my $interval = time - $start;
$start += $interval;
mail(sprintf("INTERNET -> %s for %d seconds\n",
$up ? "JUST CAME BACK - Was DOWN"
: "JUST GONE DOWN - Was UP",
$interval));
}
} while sleep 1;
评论
\ $ \ begingroup \ $
@ChrisWue POSIX :: strftime()的格式说明符与系统有关:“如果您希望代码具有可移植性,则您的format(fmt)参数应仅使用ANSI C标准定义的格式说明符。 ”您可以使用POSIX :: strftime :: GNU来避免依赖系统库支持。
\ $ \ endgroup \ $
– 200_success
14-10-27在21:30