This script scans IP's and returns a status of Up or Down. How can I alter it so it doesn't scan everything twice? As it sits it scans everything and returns the "Up" addresses only and then scans all over again and only returns the "Down" status addresses.


  ping -c 1 $1 > /dev/null
  [ $? -eq 0 ] && echo $i,Up
  [ $? -eq 1 ] && echo $i,Down

for i in 10.1.150.{1..10}
is_alive_ping $i & disown

Bonus points if anyone can make it also return the DNS name of the IP if it has one.

Thanks in advance.


The script scans each IP just once. The scanning is happening in the background (&). The down IP's take longer time to respond, that's why they are reported later.

  • where is background stuff here in shell? I guess am puzzled. Its different ping is unable to get the answer from the offline nodes and is reporting them at the end after minimal default retries. – Nikhil Mulley Jan 3 '12 at 16:21
  • @Nikhil: the function is called with & (as I also mentioned): background subshell. – choroba Jan 3 '12 at 16:27

You're looking for nmap.

# nmap -sP
Starting Nmap 5.00 ( http://nmap.org ) at 2012-01-04 00:02 CET
Host foo.example.com ( is up (0.00066s latency).
Host bar.example.com ( is up (0.00066s latency).
Nmap done: 10 IP addresses (1 host up) scanned in 1.41 seconds

ping retries for unanswering nodes, which adds to the latency in reporting the availability of the nodes back to the console output, while the answered online nodes are reported immediately back. ping has this disadvantage that you need to execute it for every host.

Use fping, a better alternative to ping , which can do a parallel ping on the hosts, source is available at sourceforge http://fping.sourceforge.net/ . Download fping and install it under /usr/local/sbin and make it suid.

Here is a perl example, that can report the unreachable nodes at the end, while the nodes that are online are reported with their dns names, you can pass the output of this script to tools such as grep or awk again to work on the desired output.

require 'open2.pl';
use Net::IP;

$pid = &open2("OUTPUT","INPUT","/usr/local/sbin/fping -d");


my $ip = new Net::IP (' -') || die "Unable to generate range\n";

do {
    push (@check, $ip->ip());
} while (++$ip);

foreach(@check) { print INPUT "$_\n"; }


while(<OUTPUT>) {
  print "$_";


If you want to keep the order you have to redirect the output not to stdout, but to files. After all pings are done, do a wait to wait for the last background process to finish. Then cat the result files in the "right" order.


adding -w to ping will allow the process to be much quicker.


  ping -c 1 -w 1 $1 > /dev/null
  [ $? -eq 0 ] && echo $i ,Alive

for i in 192.168.213.{1..254}
is_alive_ping $i &

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.