Bash script for ping in your own subnet

I have a question for one who wants to help me.

I want to create a bash script to ping IP-adresses. It must first ask me the beginnen IP, then the ending IP like: 192.168.100.1 - 192.168.100.255.
When nothing is filled in, then it must find my subnet and ping that, like when my ip is 192.168.100.6, it must ping from 192.168.100.1 - 192.168.100.255.

Yes I do have a script where the IP is already filled in, but not one, which knows in which subnet you are, to ping all of the IP adresses there...

How can I accomplish this?
Help is welcome!

If you want to know your external IP, this is the simplest way:

IP="$(curl -s jackson.io/ip/)"

If you want to know your local IP, this should work:

DEV="$(netstat -nr | sed -n '/^0.0/s/.* //p')"
IP="$(/sbin/ifconfig $DEV 2>/dev/null | sed -n '/net /s/.*addr:\([0-9.]*\).*/\1/p')"

netmask (utility of the Debian project) can be useful

~$ netmask -r 192.168.100.6/24
192.168.100.0-192.168.100.255 (256)

perts of the the man page:

SYNOPSIS
       netmask [ options ] spec [ spec ... ]
DESCRIPTION
       This  program  accepts and produces a variety of common network address and netmask formats.  Not only can it convert address and
       netmask notations, but it will optimize the masks to generate the smallest list of rules.  This is very handy if you've ever con
       figured  a  firewall  or  router and some nasty network administrator before you decided that base 10 numbers were good places to
       start and end groups of machines.

(...)

DEFINITIONS
       A spec is an address specification, it can look like:

address             One address.
address1:address2   All addresses from address1 to address2.
address1:+address2  All addresses from address1 to address1+address2.
address/mask        A group starting at address spanning mask.

       An address is an internet network address, it can look like:
ftp.gnu.org   An internet hostname.
209.81.8.252  A standard dotted quad internet address notation.
100           A decimal number (100 in this case).
0100          An octal number preceded by "0" (64 in this case).
0x100         A hexadecimal number preceded by "0x" (256 in this case).

       A mask is a network mask, it can look like:
255.255.224.0  A dotted quad netmask (netmask will complain if it is not a valid netmask).
0.0.31.255     A Cisco style inverse netmask (with the same checks).
8              The number of bits set to one from the left (CIDR notation).
010            The number of bits set to one from the left in octal.
0x10           The number of bits set to one from the left in hexadecimal.

AUTHOR
       netmask was written by Robert Stone.  Some algorithm design and optimization was provided by Tom  Lear.   This  manual  page  was
       written by Robert Stone.

I use the script below to see my own IP from bash script:

#!/bin/bash
ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' |
cut -d: -f2 | awk '{ print $1 }'

It will show your IP. If my IP is something like 192.168.1.5, it has to ping every addres in the 192.168.1.* segment.
This script must also ping every address when I am also in a different segment like 192.1.1.*

How can I accomplish that?

---------- Post updated at 06:55 AM ---------- Previous update was at 06:18 AM ----------

The above will only grep the whole ip. I want to grep 192.168.1.
Only the first 3 adresses. The last one will be filled in by a sequence {1..255}

The question is how to grep the first 3 numbers. now it is 192.168.1 but on a different subnet it could be something like 10.1.1.*

You're assuming it's a 24-bit subnet. That's usually a good assumption with a local address like 192.168.x.x. But there's no reason it couldn't be a 16-bit or 26-bit or other size subnet (16-bit or larger for 192.168).

The Genmask column of the netstat -nr command output reveals the size of the netmask. A 24-bit subnet is shown as 255.255.255.0. A 27-bit subnet would be 255.255.255.224. Both are legitimate.

To answer your 3-number question:

IP=192.168.1.5
SUBNET=${IP%.*}
echo $SUBNET
192.168.1

Here is my try, matching output for IP in all interfaces on machine.
Ping it once, if ping failes, print it (or do whatever you want there)

/inet addr:?[0-9]*.?[0-9]+\.[0-9]+\.[0-9]+/ {
gsub("(addr:|addr:127.0.0.1|.[0-9]*$)","",$2)
split($2,ipz,"\n")
	for ( i in ipz)
		for ( j=1; j <= 255; j++ )
		if (system("ping -c 1 " ipz"."j ) != 0)
		print "ping FAILED on "ipz"."j
}

Save this as pong.awk and run like

ifconfig | awk -f pong.awk

It will take a while ofcourse to 'scan' everything, if you have multiple interfaces in various subnets.

Yhat's why you can use the IP command to get information about address - mask, i.e: ip addr show eth0 returns me

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:21:97:22:e8:4d brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.2/28 brd 192.168.0.15 scope global eth0

You can then tail/grep/sed/awk or what you can to get what you need (in this example, the mask has 28 bits).

You can also try ip route list which gives other useful information.

All those commands can be used to get info to ping the whole subnet.

Hmm.. the bash script is not working..
But this one is usefull, thanks for that!

IP=192.168.1.5 SUBNET=${IP%.*} echo $SUBNET 192.168.1

And now the second part: the below script will ping the given ip adress:

echo "Enter IP-addres:"
read host1
ping -c 1 $host1 

How can I ping from $host to $host2 in the below script??

echo "Enter beginning IP-addres:"
read host1
echo "Enter ending IP-addres:"
read host2
ping -c 1 $host1 [..] $host2 

Something else then [..] must be filled in, so I can ping from beginnin ip (something like 192.168.1.1) till ending ip (something like 192.168.1.100)

The seq command may come in handy.

N=100
for n in $(seq 1 $N); do
    echo Do something with $n
done

Only if netmask is 255.255.255.0 (24 bits)
#!/bin/bash
read -p "Enter beginning IP-addres: " host1
read -p "Enter ending IP-addres: " host2
SUBNET=${host1%.*}
netId1=${host1#$SUBNET.}
netId2=${host2#$SUBNET.}
for ((i=netId1; i<=netId2; i++)); do
ping -c 1 ${SUBNET}.$i
done

What in the above script will change when it is 255.255.254.0?

And if I run the above script I get the next error:

unix1: line 7: ((: .100: syntax error: operand expected (error token is ".100")

Thanks frans, I think we are in the right direction.

I think you're missing a dot.

netId1=${host1#$SUBNET.}
netId2=${host2#$SUBNET.}
1 Like

OMG :frowning:
I'll correct the original post.
Thanks

Many thanks for this one...
The above script is working! I can ping from beginning to ending IP-adresses very fast!

Lets go to the second part... :slight_smile:
When no beginning and ending IP is given, so when the fields are empty.
The script must ping my own subnet!
This is the subnet where the system is logged in. So if I am in 192.168.100.* segmet it must ping from 192.168.100.1 to 192.168.100.255..

How can we accomplish this?

---------- Post updated at 08:35 AM ---------- Previous update was at 08:32 AM ----------

Or... the second part can be done like:

ping -b x.x.x.255

the tripple x must be filled in my the script by grepping my ip and pasting it there.

So far so good.....

ifconfig | grep 'Bcast:' | cut -d: -f3 | awk '{print $1}'

with the above I can see by broadcast IP...
but how can I tell the script in the same line to ping the output??

Output for: ifconfig | grep 'Bcast:' | cut -d: -f3 | awk '{print $1}' is 192.168.101.255 or something else. How can I also ping -b the output?

Thanks in advance