问题
Scripting and want to ping devices on a network, tell me if it's reachable or not, and then get the ttl data from the ping and tell me the operating system.
Ive tried using the awk command, but I am also new to scripting and may not be using it correctly.
for host in $(seq 1 255);
do
ping -c 1 $sn.$host | grep "Unreachable" &>/dev/null
if [ $? -eq 0 ]; then
printf "%s\n" "$sn.$host is Offline"
fi
ping -c 1 $sn.$host | grep "ttl" &>/dev/null
if [ $? -eq 0 ]; then
printf "%s\n" "$sn.$host is Online"
fi
done
I need the ttl value and to store it into a variable and then tell me what operating system it is based on Linux has a ttl of 64, windows a ttl of 128, and ios of 255
回答1:
You can do things in a bit more concise manner and minimize the time waiting for an Offline host by setting a timeout using the -w
(or -W
) option. For example you can save the ttl=XX
value from ping
in the same call that determines whether the host is online or not and then you can use a simple parameter expansion to extract the numeric ttl
value from the right side of the equal sign, e.g.
ttlstr=$(ping -c1 -w1 $sn.$host | grep -o 'ttl=[0-9][0-9]*')
Above the command substitution $(...)
executes ping
and pipes the output to grep
and assigns the results to ttlstr
. The command substitution return is the return of the last command in the pipeline telling you whether grep
for "ttl=####"
succeeded or failed. That's all you need to determine whether the host is online or not. On failure output your "Offline"
message and try the next, e.g.
## ping with 1 sec timeout store ttl=xx in ttlstr
ttlstr=$(ping -c1 -w1 $sn.$host | grep -o 'ttl=[0-9][0-9]*') || {
printf "%s is Offline\n" "$sn.$host"
continue;
}
If the command substitution succeeds, you can output your "Online" message and you can isolate the numeric ttl
using a simple parameter expansion to remove all characters up to, and including, the '='
sign from the beginning of the string leaving only the numeric ttl
, e.g.
ttl="${ttlstr#*=}" ## parameter expansion separating numeric ttl
printf "%s is Online, ttl=%d\n" "$sn.$host" "$ttl"
Putting it altogether you could do:
#!/bin/bash
sn=${1:-192.168.6}
for host in $(seq 1 255); do
## ping with 1 sec timeout store ttl=xx in ttlstr
ttlstr=$(ping -c1 -w1 $sn.$host | grep -o 'ttl=[0-9][0-9]*') || {
printf "%s is Offline\n" "$sn.$host"
continue;
}
ttl="${ttlstr#*=}" ## parameter expansion separating numeric ttl
printf "%s is Online, ttl=%d\n" "$sn.$host" "$ttl"
done
Example Use/Output
note: the sn
is taken as the 1st argument to the program (using a default of 192.168.6
above)
$ bash ~/scr/utl/chksubnet.sh
<snip>
192.168.6.14 is Offline
192.168.6.15 is Offline
192.168.6.16 is Offline
192.168.6.17 is Online, ttl=64
192.168.6.18 is Offline
192.168.6.19 is Offline
<snip>
Look things over and let me know if you have further questions.
回答2:
Here's a way of using awk to extract the ttl:
$ ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=53 time=48.575 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 48.575/48.575/48.575/0.000 ms
$ ping -c 1 8.8.8.8 | awk -F'[ =]' '/ttl/ {print $8 }'
53
The -F parameter tells awk what the field separator is. I've indicated spaces or the equals sign. The body of the awk script is written as pattern / command pairs. In the one line script, awk runs the print $8 command for any line that has ttl in line. The command tells awk to print the eigth field (remember, the -F indicated how to break the input line into fields. The /ttl/ pattern could be replaced with $7 == "ttl", too. This latter form is more accurate, since it would only match ttl if it appeared as the 7th field.
There are better more general implementations.
If you want to do this quickly, review the nmap utility. For example,
nmap -sn 192.168.1.0/24
Nmap aside, your program can be improved a bit by ping'ing the IP once and piping the results to awk, letting awk generate ALL the output.
回答3:
Below is the script which you can use to find the Operating System name based on the ttl value if host is Online.
for host in $(seq 1 255);
do
ping -c 1 $sn.$host | grep "Unreachable" &>/dev/null
if [ $? -eq 0 ]
then
printf "%s\n" "$sn.$host is Offline"
continue
else
printf "%s\n" "$sn.$host is Online"
ttlValue=`ping -c 1 $sn.$host | grep ttl | awk '{print $6}'|awk -F'=' '{print $2}' &>/dev/null`
if [ $ttlValue -eq 64 ]
then
echo "Operating is Linux"
elif [ $ttlValue -eq 128 ]
then
echo "Operating is Windows"
else
echo "Operating is IOS"
fi
fi
done
来源:https://stackoverflow.com/questions/57916431/if-i-wanted-to-extract-the-ttl-and-display-it-from-the-ping-command-how-could-i