とある事情で、大量のマシンの生存確認をすることに。
Net::Pingを使えば、pingのほかにもTCP/IPのサービスが使えるかどうかも一度にチェックできて便利すぎる。
Net::Ping - check a remote host for reachability - metacpan.org
use strict; use warnings; use Net::Ping; my $host = shift; my @serv = qw(telnet ftp ssh); # ICMP(ping) ckeck my $p = Net::Ping->new('icmp'); # set 1 if you want Time::HiRes time $p->hires(1); print "connectivity check of $host\n\n"; my ($ret, $duration, $ip) = $p->ping($host); printf("icmp\t: %s (%.3f sec)\n", ($ret ? 'OK' : 'NG'), $duration); $p->close(); # TCP check $p = Net::Ping->new('tcp'); $p->hires(1); foreach my $s (@serv){ # if port_number is set, $p->service_check(1) is automatically called to check ECONNREFUSED $p->port_number(scalar getservbyname($s, 'tcp')); ($ret, $duration, $ip) = $p->ping($host); printf("%s\t: %s (%.3f sec)\n", $s, ($ret ? 'OK' : 'NG'), $duration); } $p->close();
$ perl ckip.pl hostname connectivity check of hostname icmp : OK (0.004 sec) telnet : NG (4.993 sec) ftp : NG (4.999 sec) ssh : OK (0.002 sec)
こんな感じかなあ。
デフォルトの挙動では、TCP echoで接続しようとするらしいので、明示的にping(ICMP)を送りたいときは 'icmp' を指定してnewする必要があります。
また、TCP echoで接続した結果、RSTが返されても結果は成功と判断されるので、それがイヤな場合は service_check(1) を実行しておくと3-way handshakeが成功したときに結果が成功という風にしてくれるようです。
明示的にTCP portを指定した場合は、暗黙的にservice_check(1)が実行されるのでご注意。それがイヤなら*1port_numberを実行してからpingを実行する間に service_check(0) を呼んでおけばOK。
余談ですが、cygwinの/etc/servicesにはsshのエントリーがないみたい。ssh使えるのに結果が失敗って、どういうことだ・・・と一瞬悩んでしまった。ssh関連のパッケージをインストールすれば、追加してくれるのかも(未確認)。
*1:まあ、イヤなケースは少ないだろうけど