How can I write a linux bash script, that tells me which computers are ON in my LAN ?
It would help if I could give it as input a range of IP's.
-
If you're limiting yourself to only having the last octet changing, this script should do it. It should be fairly obvious how to extend it from one to multiple octets.
#! /bin/bash BASE=$1 START=$2 END=$3 counter=$START while [ $counter -le $END ] do ip=$BASE.$counter if ping -qc 2 $ip then echo "$ip responds" fi counter=$(( $counter + 1 )) done
shodanex : This just to long !! -
Assuming my network is 10.10.0.0/24, if i run a ping on the broadcast address like
ping -b 10.10.0.255
I'll get an answer from all computers on this network that did not block their ICMP ping port.
64 bytes from 10.10.0.6: icmp_seq=1 ttl=64 time=0.000 ms 64 bytes from 10.10.0.12: icmp_seq=1 ttl=64 time=0.000 ms 64 bytes from 10.10.0.71: icmp_seq=1 ttl=255 time=0.000 ms
So you just have to extract the 4th column, with awk for example:
ping -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }' 10.10.0.12: 10.10.0.6: 10.10.0.71: 10.10.0.95:
Well, you will get duplicate, and you may need to remove the ':'.
EDIT from comments : the -c option limits the number of pings since the script will end, we can also limit ourself on unique IPs
ping -c 5 -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }' | sort | uniq
Ben : ping -b 10.10.0.255 | awk '{ print $4 }' | sort | uniq will remove the duplicatesJochen Walter : @Ben: You should add the -c option in the call to ping, because otherwise it won't terminate.shodanex : It does not work for me, but the nmap solution doeschburd : the -b option is not present for all pings. for example it is OK on my OpenSuse, but not on my Mac, you still can try without this option -
In the real world, you could use nmap to get what you want.
nmap -sP 10.1.1.1-255
This will ping all the addresses in the range 10.1.1.1 to 10.1.1.255 and let you know which ones answer.
Of course, if you in fact want to do this as a bash exercise, you could run ping for each address and parse the output, but that's a whole other story.
-
Also using the "ping the broadcast address" method pointed out by chburd, this pipe should do the trick for you:
ping -c 5 -b 10.11.255.255 | sed -n 's/.* \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p' | sort | uniq
Of course, you'd have to change the broadcast address to that of your network.
-
Just for fun, here's an alternate
#!/bin/bash nmap -sP 192.168.1.0/24 > /dev/null 2>&1 && arp -an | grep -v incomplete | awk '{print$2}' | sed -e s,\(,, | sed -e s,\),,
hlovdal : You can combine <> into just < > Eddy : Cool, thanks for the hint -
Kalmi : "ip neighbor" and "arp -a" won't show machines with which you have not communicated for a while (or at all)
-
As other posters pointed out,
nmap
is the way to go, but here's how to do the equivalent of a ping scan in bash. I wouldn't use the broadcast ping, as a lot of systems are configured not to respond to broadcast ICMP nowadays.for i in $(seq 1 254); do host="192.168.100.$i" ping -c 1 -W 1 $host &> /dev/null echo -n "Host $host is " test $? -eq 0 && echo "up" || echo "down" done
-
There is also fping:
fping -g 192.168.1.0/24
or:
fping -g 192.168.1.0 192.168.1.255
or show only hosts that are alive:
fping -ag 192.168.1.0/24
It pings hosts in parallel so the scan is very fast. I don't know a distribution which includes
fping
in its default installation but in most distributions you can get it through the package manager. -
I would suggest using nmap's ping-scan flag,
$ nmap -sP 192.168.1.60-70 Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-04-09 20:13 BST Host machine1.home (192.168.1.64) appears to be up. Host machine2.home (192.168.1.65) appears to be up. Nmap finished: 11 IP addresses (2 hosts up) scanned in 0.235 seconds
That said, if you want to write it yourself (which is fair enough), this is how I would do it:
for ip in 192.168.1.{1..10}; do ping -t 1 $ip > /dev/null && echo "${ip} is up"; done
..and an explanation of each bit of the above command:
Generating list of IP addresses
You can use the
{1..10}
syntax to generate a list of numbers, for example..$ echo {1..10} 1 2 3 4 5 6 7 8 9 10
(it's also useful for things like
mkdir {dir1,dir2}/{sub1,sub2}
- which makesdir1
anddir2
, each containingsub1
andsub2
)So, to generate a list of IP's, we'd do something like
$ echo 192.168.1.{1..10} 192.168.1.1 192.168.1.2 [...] 192.168.1.10
Loops
To loop over something in bash, you use
for
:$ for thingy in 1 2 3; do echo $thingy; done 1 2 3
Pinging
Next, to ping.. The ping command varies a bit with different operating-systems, different distributions/versions (I'm using OS X currently)
By default (again, on the OS X version of
ping
) it will ping until interrupted, which isn't going to work for this, soping -c 1
will only try sending one packet, which should be enough to determine if a machine is up.Another problem is the timeout value, which seems to be 11 seconds on this version of ping.. It's changed using the
-t
flag. One second should be enough to see if a machine on the local network is alive or not.So, the ping command we'll use is..
$ ping -c 1 -t 1 192.168.1.1 PING 192.168.1.1 (192.168.1.1): 56 data bytes --- 192.168.1.1 ping statistics --- 1 packets transmitted, 0 packets received, 100% packet loss
Checking ping result
Next, we need to know if the machine replied or not..
We can use the
&&
operator to run a command if the first succeeds, for example:$ echo && echo "It works" It works $ nonexistantcommand && echo "This should not echo" -bash: nonexistantcommand: command not found
Good, so we can do..
ping -c 1 -t 1 192.168.1.1 && echo "192.168.1.1 is up!"
The other way would be to use the exit code from ping.. The ping command will exit with exit-code 0 (success) if it worked, and a non-zero code if it failed. In bash you get the last commands exit code with the variable
$?
So, to check if the command worked, we'd do..
ping -c 1 -t 1 192.168.1.1; if [ $? -eq 0 ]; then echo "192.168.1.1 is up"; else echo "ip is down"; fi
Hiding ping output
Last thing, we don't need to see the ping output, so we can redirect
stdout
to/dev/null
with the>
redirection, for example:$ ping -c 1 -t 1 192.168.1.1 > /dev/null && echo "IP is up" IP is up
And to redirect
stderr
(to discard theping: sendto: Host is down
messages), you use2>
- for example:$ errorcausingcommand -bash: errorcausingcommand: command not found $ errorcausingcommand 2> /dev/null $
The script
So, to combine all that..
for ip in 192.168.1.{1..10}; do # for loop and the {} operator ping -c 1 -t 1 192.168.1.1 > /dev/null 2> /dev/null # ping and discard output if [ $? -eq 0 ]; then # check the exit code echo "${ip} is up" # display the output # you could send this to a log file by using the >>pinglog.txt redirect else echo "${ip} is down" fi done
Or, using the
&&
method, in a one-liner:for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
Problem
It's slow.. Each ping command takes about 1 second (since we set the -t timeout flag to 1 second). It can only run one ping command at a time.. The obvious way around this is to use threads, so you can run concurrent commands, but that's beyond what you should use bash for..
"Python threads - a first example" explains how to use the Python threading module to write a multi-threaded ping'er.. Although at that point, I would once again suggest using
nmap -sP
..Ash Kim : *** slow clap ***CodeJoust : Is there a way to create and initiate threads in BASH? This probably could be done in ruby/python as a script just opening an Network connection, but could the same ability to create multiple threads can be done in BASH?dbr : You could run the process in the background the command by doing `mycmd &`, but that's not really threading, and could become quite complicated if you need the output of several commands.. It would be much simpler to just use Python/Ruby/etc.. -
please try this,,,more faster,,,tnks for all,,,
!/bin/bash
for ((n=0 ; n < 30 ; n+=1)) do ip=10.1.1.$n if ping -c 1 -w 1 $ip > /dev/null 2> /dev/null >> /etc/logping.txt; then
echo "${ip} is up" # output klien up # sintax >> /etc/logping.txt to create log with .txt format else echo "${ip} is down" # output klien downfi done
-
#!/bin/bash for ((n=0 ; n < 30 ; n+=1)) do ip=10.1.1.$n if ping -c 1 -w 1 $ip > /dev/null 2> /dev/null >> /etc/logping.txt; then echo "${ip} is up" # output up # sintax >> /etc/logping.txt log with .txt format else echo "${ip} is down" # output down fi done
-
#!/bin/bash #Get the ip address for the range ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' | cut -d"." -f1,2,3) # ping test and list the hosts and echo the info for range in $ip ; do [ $? -eq 0 ] && ping -c 1 -w 1 $range > /dev/null 2> /dev/null && echo "Node $range is up" done
0 comments:
Post a Comment