It is occasionally useful to check (or scan) an IP address range for active devices. One easy method sends ICMP Echo Request packets and expects answers in the form of ICMP Echo Reply packets, like the ping program does. Sending ICMP Echo Request packets to a range of IP addresses is sometimes called a ping sweep.
Usually programs like fping, nmap, or Angry IP Scanner are used for this kind of network scan. Sometimes none of these are available, but a basic UNIX-like system is. In these circumstances (e.g., with a basic Solaris 10 install) my ping_scan shell script below can be used. If available, BASH brace expansion, seq, or jot can be used to create a list of IP addresses. prips is a small tool to generate a list of IP addresses from a range or network description. I have written a shell script named net2ips that returns all host IP addresses of a given IP network. My net2ips.py is a similar script written in Python 3 that supports both IPv4 and IPv6. My Python 3 script ipenum.py extends this to also accept range descriptions using start and end addresses.
To stress one point: ping_scan is supposed to be usable without a compiler, without root permissions, and without installation. Thus it is a shell script relying on the widely available ping program for ICMP.
Shell script ping_scan
ping_scan [-h] [-L] [-V] [-t TIMEOUT] [-v] [-u] [IP...]
-h print this help and exit -t TIMEOUT specify the timeout value used for ping (default 1s) -v print additional runtime info -u print not reachable hosts instead -L print license and exit -V print version information and exit
ping_scan sends ICMP echo requests to the hosts (IP addresses) specified and prints every host that answers with an ICMP echo reply.
Specify IP addresses as command line arguments. If no IP addresses are given as arguments, IP addresses are read from STDIN, one IP address per line.
With the -u option, only hosts / IP addresses from whom no answer was received inside the timeout are printed.
The environment variable PING_WRAPPER can be used to specify a different ping program, e.g. my ping_wrapper script (see below).
$ ping_scan 8.8.8.8 8.8.4.4 8.8.4.4 is alive 8.8.8.8 is alive $ ping_scan -v 8.8.8.8 8.8.4.4 Sending ICMP echo requests and waiting for results... (timeout 1s) 8.8.4.4 is alive 8.8.8.8 is alive $ env PING_WRAPPER=~/bin/ping_wrapper ping_scan -v -t5 8.8.8.8 8.8.4.4 Sending ICMP echo requests and waiting for results... (timeout 5s) 8.8.4.4 is alive 8.8.8.8 is alive $ env PING_WRAPPER=./ping_wrapper ./ping_scan -t5 -u 9.9.9.9 8.8.8.8 7.7.7.7 no answer from 7.7.7.7 $ env PING_WRAPPER=./ping_wrapper ./ping_scan -t5 -uv 9.9.9.9 8.8.8.8 7.7.7.7 Sending ICMP echo requests and waiting for results... (timeout 5s) Printing not reachable hosts. no answer from 7.7.7.7 $ time ping_scan 131.246.124.{65..126} 131.246.124.65 is alive 131.246.124.67 is alive 131.246.124.69 is alive 131.246.124.70 is alive 131.246.124.71 is alive 131.246.124.72 is alive 131.246.124.73 is alive 131.246.124.74 is alive 131.246.124.75 is alive 131.246.124.76 is alive 131.246.124.77 is alive 131.246.124.78 is alive 131.246.124.79 is alive 131.246.124.80 is alive 131.246.124.81 is alive 131.246.124.82 is alive 131.246.124.83 is alive 131.246.124.84 is alive 131.246.124.85 is alive 131.246.124.87 is alive 131.246.124.89 is alive 131.246.124.90 is alive 131.246.124.91 is alive 131.246.124.93 is alive 131.246.124.96 is alive 131.246.124.97 is alive 131.246.124.98 is alive 131.246.124.99 is alive 131.246.124.102 is alive 131.246.124.103 is alive 131.246.124.104 is alive 131.246.124.106 is alive 131.246.124.107 is alive 131.246.124.124 is alive 131.246.124.125 is alive 131.246.124.126 is alive real 0m1.636s user 0m0.116s sys 0m1.060s
$ ping_scan 131.246.124.{65..126} | wc -l 36
$ ping_scan 192.0.2.{1..254} > pre_change_replies $ # implement some network changes... $ ping_scan 192.0.2.{1..254} > post_change_replies $ diff -U0 pre_change_replies post_change_replies | egrep -v -- '^(--|\+\+|@@)'
Lines staring with '+' are new after the change, those staring with '-' are missing after the change.
The shell script ping_wrapper is intended to make the ping program from iputils, which is the most commonly used ping program on GNU/Linux systems, usable with ping_scan (see above).
Shell script ping_wrapper
ping_wrapper [-n] host [timeout]
$ ping_wrapper 127.0.0.1 127.0.0.1 is alive $ ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.054 ms 64 bytes from 127.0.0.1: icmp_req=2 ttl=64 time=0.045 ms 64 bytes from 127.0.0.1: icmp_req=3 ttl=64 time=0.039 ms ^C --- 127.0.0.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.039/0.046/0.054/0.006 ms
ping_scan
On a modern GNU/Linux system you can use the tools installed by default for a quick enough ping scan:
$ for i in 192.168.254.{1..254}; do ping -c1 -q -W1 "$i" 2>/dev/null& sleep .01; done | fgrep -B1 '1 received' --- 192.168.254.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.2 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.120 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.121 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.125 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.126 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.129 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms -- --- 192.168.254.130 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0msTo create the same output as ping_scan you can use:
$ for i in 131.246.124.{65..70}; do ping -c1 -q -W1 "$i" 2>/dev/null& sleep .01; done | sed -n '/^---/{N;s/^--- \([^ ]*\) .*\n1 [^1]*1 rec.*$/\1 is alive/p}' 131.246.124.65 is alive 131.246.124.66 is alive 131.246.124.69 is alive 131.246.124.67 is alive 131.246.124.70 is aliveTo show just the hosts that do not answer to ping you can use:
$ for i in 192.0.2.{1..254}; do ping -c1 -q -W1 "$i" 2>/dev/null& sleep .01; done | sed -n '/^---/{N;s/^--- \([^ ]*\) .*\n1 [^1]*0 rec.*$/no answer from\1/p}'To show both answering (alive) and non-answering hosts you can use:
$ for i in 192.0.2.{1..254}; do ping -c1 -q -W1 "$i" 2>/dev/null& sleep .01; done sed -n '/^---/{N;s/^--- \([^ ]*\) .*\n1 [^1]*1 rec.*$/\1 is alive/p;s/^--- \([^ ]*\) .*\n1 [^1]*0 rec.*$/\1 does not answer/p}' | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n
fping
To get a similar output as ping_scan with fping (without the words is alive) use:
$ fping -a -g 172.29.29.0/24 -q -r 0 172.29.29.1 172.29.29.2 172.29.29.29 172.29.29.233
back to my homepage.