0

I need to perform a ping sweep of a range of 254 hosts,e.g. X.X.X.1 - X.X.X.254 and output the results to a file for later manipulation. Currently I have a bash script that does this for me, however, it is incredibly slow. Is there anyway to speed this up? If possible, I would like to be able to use the ping command and utilize bash for the scripting language.

My script is as follows:

#!/bin/bash

for i in {1..254}
do
    ping -c 1 X.X.X.$i >> results.txt
done

NOTE: I do not actually have the characters 'X.X.X' in my code, rather I have the actual IP address.

  • 1
    You'll need to have a timeout - pings don't always fail fast .. – Mr R Mar 16 '21 at 12:32
  • 2
    just launch them all in the background? add "&". (sort the results later) – Fattie Mar 16 '21 at 12:32
  • https://unix.stackexchange.com/questions/524963/how-can-i-ping-multiple-ip-addresses-at-the-same-time – KamilCuk Mar 16 '21 at 12:35
  • Use the `xargs -Pn` technique - see https://stackoverflow.com/questions/3004811/how-do-you-run-multiple-programs-in-parallel-from-a-bash-script - which is a very cool way of running a subset of "M" in parallel from a pool of "N". – Mr R Mar 16 '21 at 12:35
  • 2
    You could use a specialized network probing tool like nmap: `nmap -nsP 192.0.2.0/24` [RFC-5737: IPv4 Address Blocks Reserved for Documentation](https://tools.ietf.org/html/rfc5737) – Léa Gris Mar 16 '21 at 13:24
  • ```fping -g X.X.X.1 X.X.X.254``` – Maxim Sagaydachny Mar 16 '21 at 17:09

1 Answers1

0

As a Nagios monitoring administrator I wrote this Perl script back in the day to verify if the hosts are pinging. Sometimes, I needed to check hundreds of hosts and I needed quicker response time too.

As you are using Linux you might find this script better suited for your requirements as Perl comes pre-installed on majority of Linux / Unix distributions.

If you need to create a file with IP addresses, you can just do something like below on the command line:

$ seq -f "192.168.0.%g" 1 255 > ip_range.txt

This will create file for you with IP range from 192.168.0.1 to 192.168.0.255 and then you can use my script to ping this range:

$ perl ping_hosts.pl ip_range.txt

For verification purpose I just re-ran this script with 694 hosts out of which 128 hosts were either dead of wrong hostnames, it returned the output in 1 minute and 6 seconds.

real    1m6.281s
user    0m0.265s
sys     0m0.137s

ping_hosts.pl

#!/usr/bin/perl

use strict;
use warnings;
use Net::Ping;

my (@alive_hosts, @dead_hosts);

my $in_file = $ARGV[0];

open *DATA, "<", $in_file or die "$!\n" if $in_file;
my @data = <DATA>;
chomp @data;

#my %uniq;
#my @hosts = grep { ! $uniq{$_}++ } @data;
my @hosts = keys %{{ map {lc $_ => 1} grep {/\S/} @data }};

my $p = Net::Ping->new("icmp");

for my $host (@hosts) {
        print "checking $host - ";
        if ($p->ping($host)) {
                print "up\n";
                push @alive_hosts, $host;
        } else {
                print "down\n";
                push @dead_hosts, $host;
        }
}

print "\n";

if (@alive_hosts) {
        print "Possible alive hosts\n";
        print "=" x 10, "\n";
        print join "\n", sort { $a cmp $b } @alive_hosts;
        print "\nTotal = ", scalar(@alive_hosts);
        print "\n\n";
}

if (@dead_hosts) {
        print "Hosts not responding to ping\n";
        print "=" x 10, "\n";
        print join "\n", sort { $a cmp $b } @dead_hosts;
        print "\nTotal = ", scalar(@dead_hosts);
        print "\n";
}

__DATA__

CAVEAT: If you are using this script on all dead hosts then it will be a super-slow script.

Ashish Kumar
  • 811
  • 4
  • 8