blizz_ard
asked on
Net::Ping unexpected result
use Net::Ping;
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
The result of this is always null, stating that $host is not up. I checked the host and it is up by doing a ping manually. Why is $r always null? Is there something i did wrong
using icmp works well with the expected result. But it requires to run as root. I do not want to run the script as root.
Thanks.
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
The result of this is always null, stating that $host is not up. I checked the host and it is up by doing a ping manually. Why is $r always null? Is there something i did wrong
using icmp works well with the expected result. But it requires to run as root. I do not want to run the script as root.
Thanks.
Using Net::Ping "tcp" protocol requires that the target host respond on the "echo" port, port 7. Most hosts no longer keep this service open. You may have better results from using "external", which will just use the same ping command you used from the command line.
ASKER
Here is the output:
discord{ysialend}:80 ~> more test1.pl
#!/usr/local/bin/perl
use Net::Ping;
$host = "172.17.45.8";
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
print "I'm up\n" if $r;
print "I'm down\n" if !$r;
discord{ysialend}:81 ~> ping 172.17.45.8
172.17.45.8 is alive
discord{ysialend}:82 ~> test1.pl
I'm down
discord{ysialend}:83 ~>
discord{ysialend}:80 ~> more test1.pl
#!/usr/local/bin/perl
use Net::Ping;
$host = "172.17.45.8";
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
print "I'm up\n" if $r;
print "I'm down\n" if !$r;
discord{ysialend}:81 ~> ping 172.17.45.8
172.17.45.8 is alive
discord{ysialend}:82 ~> test1.pl
I'm down
discord{ysialend}:83 ~>
ASKER
Here is the output:
discord{ysialend}:80 ~> more test1.pl
#!/usr/local/bin/perl
use Net::Ping;
$host = "172.17.45.8";
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
print "I'm up\n" if $r;
print "I'm down\n" if !$r;
discord{ysialend}:81 ~> ping 172.17.45.8
172.17.45.8 is alive
discord{ysialend}:82 ~> test1.pl
I'm down
discord{ysialend}:83 ~>
discord{ysialend}:80 ~> more test1.pl
#!/usr/local/bin/perl
use Net::Ping;
$host = "172.17.45.8";
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
print "I'm up\n" if $r;
print "I'm down\n" if !$r;
discord{ysialend}:81 ~> ping 172.17.45.8
172.17.45.8 is alive
discord{ysialend}:82 ~> test1.pl
I'm down
discord{ysialend}:83 ~>
ASKER
Ok..
I'm doing this now:
$r = `ping $host`;
print "I'm up" if $r =~ /^alive$
print "I'm down" if $r =~ /^no answer$
But the exteranl ping command does not give me the option to specify timeout. So, if a host is unreachable, it will wait around for a good 20 seconds before returning a value.
How do I specifiy a timeout value for this, so that it will try to ping for 2 seconds, and return a value if it has tried for more than 2 seconds?
Thanks
I'm doing this now:
$r = `ping $host`;
print "I'm up" if $r =~ /^alive$
print "I'm down" if $r =~ /^no answer$
But the exteranl ping command does not give me the option to specify timeout. So, if a host is unreachable, it will wait around for a good 20 seconds before returning a value.
How do I specifiy a timeout value for this, so that it will try to ping for 2 seconds, and return a value if it has tried for more than 2 seconds?
Thanks
Well, since you posted this question twice, I thought I'd post my answer in each.
When I tested this, if unreachable, it responded back in 2 seconds. Note that you should use icmp instead of tcp since (as jmcg mentions) most hosts will not respond to the tcp ping. Or you may consider using both in a nested if statement.
#!/usr/bin/perl
use Net::Ping;
$host = "some-host";
$p = Net::Ping->new("icmp");
if ($p->ping($host)) {
print "I'm up";
} else {
print "I'm down"
}
$p->close();
When I tested this, if unreachable, it responded back in 2 seconds. Note that you should use icmp instead of tcp since (as jmcg mentions) most hosts will not respond to the tcp ping. Or you may consider using both in a nested if statement.
#!/usr/bin/perl
use Net::Ping;
$host = "some-host";
$p = Net::Ping->new("icmp");
if ($p->ping($host)) {
print "I'm up";
} else {
print "I'm down"
}
$p->close();
Here's an example of using both tcp & icmp. Depending on the host I tested this on, I was getting (failure) responses rannging from 5 to 10 seconds. The other example I gave which only used icmp failures ranged from 1.5 to 3 seconds.
#!/usr/bin/perl
use Net::Ping;
$host = "www.microsoft.com";
$p = Net::Ping->new("icmp");
if ($p->ping($host)) {
print "I'm Up\n";
} else {
$p = Net::Ping->new("tcp");
if ($p->ping($host)) {
print "I'm Up\n";
} else {
print "I'm Down\n";
}
}
$p->close();
#!/usr/bin/perl
use Net::Ping;
$host = "www.microsoft.com";
$p = Net::Ping->new("icmp");
if ($p->ping($host)) {
print "I'm Up\n";
} else {
$p = Net::Ping->new("tcp");
if ($p->ping($host)) {
print "I'm Up\n";
} else {
print "I'm Down\n";
}
}
$p->close();
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
If you don't want to use the Net::Ping module, this is what you're looking for:
#!/usr/bin/perl
$host = "www.microsoft.com";
$r = `ping $host 2`;
print "I'm up\n" if $r =~ /alive/;
print "I'm down\n" if $r =~ /no answer/;
#!/usr/bin/perl
$host = "www.microsoft.com";
$r = `ping $host 2`;
print "I'm up\n" if $r =~ /alive/;
print "I'm down\n" if $r =~ /no answer/;
There's been a "blizzard" of multiple postings, but it looks like you have enough stuff to work with.
One thing that may not be clear to FishMonger is that icmp messaging is a privileged operation on Linux/Unix (I don't know about Windows NT/2K/XP); the "icmp" option in Net::Ping may not work if you will not be running the script as root.
If the system at the other end is a web server, it may be best to try to open a connection on port 80, then close it without sending anything. This should not cost anything more than the Net::Ping "tcp" option and will test the operation you really care about rather than testing low-level network connectivity. It will also work in places where pinging does not if, for instance, there's a firewall in place that forbids icmp but allows http on port 80. You can set timeouts on this operation as well.
One thing that may not be clear to FishMonger is that icmp messaging is a privileged operation on Linux/Unix (I don't know about Windows NT/2K/XP); the "icmp" option in Net::Ping may not work if you will not be running the script as root.
If the system at the other end is a web server, it may be best to try to open a connection on port 80, then close it without sending anything. This should not cost anything more than the Net::Ping "tcp" option and will test the operation you really care about rather than testing low-level network connectivity. It will also work in places where pinging does not if, for instance, there's a firewall in place that forbids icmp but allows http on port 80. You can set timeouts on this operation as well.
jmcg, you're right. I jump between Windows, Solaris, and sometimes Red Hat, unfortunitly, I sometimes forget that the same command doesn't always work the same. Windows is a lot more relaxed on which users can use "privileged operations".
Your suggestion of testing connectivity to port 80 is probably the best.
Your suggestion of testing connectivity to port 80 is probably the best.
There's an example for doing the http check with a two-second timeout in the Net::Ping POD documentation:
$p = Net::Ping->new("tcp", 2);
# Try connecting to the www port instead of the echo port
$p->{port_num} = getservbyname("http", "tcp");
while ($stop_time > time())
{
print "$host not reachable ", scalar(localtime()), "\n"
unless $p->ping($host);
sleep(300);
}
undef($p);
where the test is repeated every 5 minutes. There's also a discussion of using SYN packets to asynchronously check multiple hosts without needing to be privileged and using Time::HiRes to get more precise measurement of ping times.
$p = Net::Ping->new("tcp", 2);
# Try connecting to the www port instead of the echo port
$p->{port_num} = getservbyname("http", "tcp");
while ($stop_time > time())
{
print "$host not reachable ", scalar(localtime()), "\n"
unless $p->ping($host);
sleep(300);
}
undef($p);
where the test is repeated every 5 minutes. There's also a discussion of using SYN packets to asynchronously check multiple hosts without needing to be privileged and using Time::HiRes to get more precise measurement of ping times.
ASKER
There's a lot of answers that I can accept, I'll accept FishMonger answer as fist come first. Thanks to all. Appreciate all the answers
ASKER
discord{ysialend}:80 ~> more test1.pl
#!/usr/local/bin/perl
use Net::Ping;
$host = "172.17.45.8";
$p = Net::Ping->new("tcp");
$r = $p->ping($host,2);
print "I'm up\n" if $r;
print "I'm down\n" if !$r;
discord{ysialend}:81 ~> ping 172.17.45.8
172.17.45.8 is alive
discord{ysialend}:82 ~> test1.pl
I'm down
discord{ysialend}:83 ~>