Show active ip-addresses in linux script with % or UP/DOWN - linux

I have an ip-address: 192.168.0.205
I can ping it in a script:
for i in 192.168.0.205 ....
do
ping -c 1 $i
done
but now I want the script shows:
192.168.0.205 UP or DOWN
Is there also a way to show it in % e.g: 75% UP?

What you may want is this:
x=0;
a=1
b=5
for((i=$a;i<=$b;i++))
do
y=`ping -n 1 192.168.1.$i | grep unreachable | wc -l`
x=$(($x + $y))
done;
echo "$x $b $a" | awk '{printf "%.2f %% DOWN\n",($1/($2-$3+1))*100}';
x: contains the number of DOWN IPs
a: last octet of first IP address
b: last octet of last IP address
y: contains 0 if an IP is UP else 1
I hope that helps!
PS: Change -n to -c or whatever option does the work in your shell!

Related

How to get output for every cpu percentage

for i in `cat servers.txt` ; do
for k in `cat ip.txt` ; do
cpu=`sshpass -f passfile ssh $i -p 8022 "sshpass -p admin ssh $k "top -n 1 | grep /system/bin/mediaserver | a
wk '{print $8*100}'""`
echo " The cpu percentage of $k is $cpu" > file
done
done
When I run the script to save the output in a file variable k has two IP addresses, but in file it is only saving the last IP address. I want to get two IP addresses output in file.

Multiple variables into one variable with wildcard

I have this script:
#!/bin/bash
ping_1=$(ping -c 1 www.test.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//')
ping_2=$(ping -c 1 www.test1.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//')
ping_3=$(ping -c 1 www.test2.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//')
ping_4=$(ping -c 1 www.test3.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//' )
Then I would like to treat the outputs of ping_1-4 in one variable. Something like this:
#!/bin/bash
if [ "$ping_*" -gt 50 ]; then
echo "One ping is to high"
else
echo "The pings are fine"
fi
Is there a possibility in bash to read these variables with some sort of wildcard?
$ping_*
Did nothing for me.
The answer to your stated problem is that yes, you can do this with parameter expansion in bash (but not in sh):
#!/bin/bash
ping_1=foo
ping_2=bar
ping_etc=baz
for var in "${!ping_#}"
do
echo "$var is set to ${!var}"
done
will print
ping_1 is set to foo
ping_2 is set to bar
ping_etc is set to baz
Here's man bash:
${!prefix*}
${!prefix#}
Names matching prefix. Expands to the names of variables whose
names begin with prefix, separated by the first character of the
IFS special variable. When # is used and the expansion appears
within double quotes, each variable name expands to a separate
word.
The answer to your actual problem is to use arrays instead.
I don't think there's such wildcard.
But you could use a loop to iterate over values, for example:
exists_too_high() {
for value; do
if [ "$value" -gt 50 ]; then
return 0
fi
done
return 1
}
if exists_too_high "$ping_1" "$ping_2" "$ping_3" "$ping_4"; then
echo "One ping is to high"
else
echo "The pings are fine"
fi
You can use "and" (-a) param:
if [ $ping_1 -gt 50 -a \
$ping_2 -gt 50 -a \
$ping_3 -gt 50 -a ]; then
...
...
Or instead of defining a lot of variables, you can make an array and check with a loop:
pings+=($(ping -c 1 www.test.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//'))
pings+=($(ping -c 1 www.test1.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//'))
pings+=($(ping -c 1 www.test2.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//'))
pings+=($(ping -c 1 www.test3.com | tail -1| awk '{print $4}' | cut -d '/' -f 2 | sed 's/\.[^.]*$//' ))
too_high=0
for ping in ${pings[#]}; do
if [ $ping -gt 50 ]; then
too_high=1
break
fi
done
if [ $too_high -eq 1 ]; then
echo "One ping is to high"
else
echo "The pings are fine"
fi
To complement the existing, helpful answers with an array-based solution that demonstrates:
several advanced Bash techniques (robust array handling, compound conditionals, handling the case where pinging fails)
an optimized way to extract the average timing from ping's output by way of a single sed command (works with both GNU and BSD/macOS sed).
reporting the servers that either took too long or failed to respond by name.
#!/usr/bin/env bash
# Determine the servers to ping as an array.
servers=( 'www.test.com' 'www.test1.com' 'www.test2.com' 'www.test3.com' )
# Initialize the array in which timings will be stored, paralleling the
# "${servers[#]}" array.
avgPingTimes=()
# Initialize the array that stores the names of the servers that either took
# too long to respond (on average), or couldn't pe pinged at all.
failingServers=()
# Determine the threshold above which a timing is considered too high, in ms.
# Note that a shell variable should contain at least 1 lowercase character.
kMAX_TIME=50
# Determine how many pings to send per server to calculate the average timing
# from.
kPINGS_PER_SERVER=1
for server in "${servers[#]}"; do
# Ping the server at hand, extracting the integer portion of the average
# timing.
# Note that if pinging fails, $avgPingTime will be empty.
avgPingTime="$(ping -c "$kPINGS_PER_SERVER" "$server" |
sed -En 's|^.* = [^/]+/([^.]+).+$|\1|p')"
# Check if the most recent ping failed or took too long and add
# the server to the failure array, if so.
[[ -z $avgPingTime || $avgPingTime -gt $kMAX_TIME ]] && failingServers+=( "$server" )
# Add the timing to the output array.
avgPingTimes+=( "$avgPingTime" )
done
if [[ -n $failingServers ]]; then # pinging at least 1 server took too long or failed
echo "${#failingServers[#]} of the ${#servers[#]} servers took too long or couldn't be pinged:"
printf '%s\n' "${failingServers[#]}"
else
echo "All ${#servers[#]} servers responded to pings in a timely fashion."
fi
Yes bash can list variables that begin with $ping_, by using its internal compgen -v command, (see man bash under SHELL BUILTIN COMMANDS), i.e.:
for f in `compgen -v ping_` foo ; do
eval p=\$$f
if [ "$p" -gt 50 ]; then
echo "One ping is too high"
break 1
fi
[ $f=foo ] && echo "The pings are fine"
done
Note the added loop item foo -- if the loop gets through all the variables, then print "the pings are fine".

How to find out your IP addresses using bash

I have a server that has several ip addresses. I want to work out their exact values in bash. I am looking for something like:
a=returnIpAddressStartingWith 10.60.12
b=returnIpAddressStartingWith 10.60.13
so that the following returns:
> echo $a
10.60.12.23
Is there a reasonable way of doing this on linux?
You can use a function like this for searching:
findip() {
ip -4 addr | awk -v ip="$1" -F '[/[:blank:]]+' '$2 == "inet" && index($3, ip){print $3}'
}
And find the IP by:
a=$(findip '10.60.12')
Parse it out of the 'ip addr show' list using grep/awk/cut, then optionally, if you need to access it as an array, copy your list into a Bash array:
# Create a string that is the list of all variables
IPSTR=`ip addr show | fgrep 'inet ' | fgrep -v '127.0.0.1' | awk '{ print $2 }' | cut -d '/' -f 1`
I=0
for IP in $IPSTR ; do
IPARY[$I]=$IP
I=$(($I+1))
done
echo "First IP in array is ${IPARY[0]}"
echo "Number of IP addresses in array is ${#IPARY[*]}"

Scripting HELP needed for finding LIVE HOSTS using bash in linux

How do I create a script that will identify all live hosts (responding to ping) using bin/bash in linux? My thoughts are to first have a
fping -A "some URL" // to get the IP address
then to set that to a var. then run a
fping -g "var" // having the ip address inserted by using a var.
Is there an easier way? If so, what would that script look like?
Not sure what you want to do and why you use fping, but if you just need the IP for a host you should use somthing like this:
getent ahostsv4 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1
getent ahostsv6 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1
getent hosts google.de | head -n 1 | cut -d ' ' -f 1
All commands will resolve an IP address if host still exist. If host points to CNAME it will also get the IP in that case.
Lets say, you have a text file containing all your hosts to test:
like: test-hosts.txt
www.server1.dom
www.server2.dom
server3.dom
1.3.5.7
then the command line (contains bash-script) will do it:
cat test-hosts.txt | xargs -i\{\} bash -c 'HOST="{}"; IP=$(getent ahostsv4 "{}" | grep STREAM | head -n 1 | cut -d " " -f 1); ping -c 1 -w 5 "$IP" >/dev/null 2>&1; RESULT="$?"; echo -e "Host: $HOST ($IP) \c"; case "$RESULT" in 0) echo "is online";; 1) echo "not responding after 5 secs";; *) if [[ "$IP" == "" ]]; then echo "has no resolveable address"; else echo "not availabe due to error [$RESULT]"; fi;; esac;'
and provide outputs like:
is online
not responding
no resolveable address
not available due error [code]

Replace ip address with hostname using sed or other command-line tool

I have a command that outputs something like this:
192.168.1.1 182
192.168.1.10 300
192.168.4.50 64
I want to pipe this through sed or some other linux command-line tool and replace the IP addresses with their hostname from the 'host ' command, like this:
web.hostname.com 182
db.hostname.com 300
search.hostname.com 64
How would I go about doing this?
Looks a bit tricky, but should do what you need:
your_command | while read HOST NUM; do host $HOST | tr "\n" " "; echo $NUM; done
I can't figure out how to get sed to use the evaluation of a command (in backticks) in the replace string and pass it one of the matched subexpressions as an argument, but maybe someone else can.
If you are in bash, you could pipe it into this:
while read ip whatever ; do hostname=`host $ip | grep pointer` ; \
if [ -n "$hostname" ] ; then echo `host $ip` $whatever | \
sed 's/\(^.* pointer \)\(.*\)\./\2/g' ; else echo $ip $whatever ; fi ; done
(This tries to pull the hostname out of the response, and leave the ip address numeric if the result of the lookup isn't a hostname)

Resources