BugBuddy
BugBuddy

Reputation: 606

Perl - How to check if a server is live using Ping?

I'm using Perl 5, version 30 on Linux. I want to check if a server is alive and I am only interested if the ping call returns true or false. Here's my (non-working) code:

#!/usr/bin/perl
use strict;
use warnings;

use Net::Ping;
my $pinger = Net::Ping->new();
if ($pinger->ping('google.com')) {
   print 'alive\n';
} else {
   print 'dead\n';
}

The code should work (I think). But it fails (returns "dead") for every server, every time. It also fails if I execute as sudo: sudo perl pingcheck.pl. (EDIT: I cannot use sudo in practice. I tried it only for troubleshooting.)

I do have Net::Ping installed:

$ cpan -l | grep Net::Ping
Net::Ping       2.71

There are no error messages from Perl.

If I do the same in bash, the ping works as expected:

$ ping -c 3 google.com
PING google.com (64.233.178.100) 56(84) bytes of data.
64 bytes from ol-in-f100.1e100.net (64.233.178.100): icmp_seq=1 ttl=43 time=49.8 ms
64 bytes from ol-in-f100.1e100.net (64.233.178.100): icmp_seq=2 ttl=43 time=49.8 ms
64 bytes from ol-in-f100.1e100.net (64.233.178.100): icmp_seq=3 ttl=43 time=50.0 ms

--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 49.754/49.846/50.011/0.116 ms

Upvotes: 2

Views: 3144

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123561

$ ping -c 3 google.com

This is doing an ICMP ping.

my $pinger = Net::Ping->new();
if ($pinger->ping('google.com')) { ...

This is NOT doing an ICMP ping. From the documentation:

You may choose one of six different protocols to use for the ping. The "tcp" protocol is the default. ... With the "tcp" protocol the ping() method attempts to establish a connection to the remote host's echo port.

The echo service is today almost never active or the port is blocked, so using this as endpoint will usually not work. If you would do instead an ICMP ping with Net::Ping it works as it does with the ping command:

my $pinger = Net::Ping->new('icmp');
if ($pinger->ping('google.com')) { ...

Note that none of this is really suitable to determine if a host is up. ICMP ping is often blocked. Instead you should check if a connection to the specific service you want to use is possible:

# check if a connect to TCP port 443 (https) is possible
my $pinger = Net::Ping->new('tcp');
$pinger->port_number(443); 
if ($pinger->ping('google.com')) { ...

Upvotes: 6

Related Questions