How to get hostname from IP address from file similar to /etc/hosts - bash

I have a file which maps IP Address to hostname. Its format is similar to hosts file and contains a list of ipaddress to hostname mapping.
eg.
10.200.99.1 master1
10.200.99.2 master2
10.200.99.3 master3
10.200.99.4 slave1
10.200.99.5 slave2
10.200.99.6 slave3
...
...
...
I would like to obtain hostname from a given ipaddress using bash script.
How can i do so?

You can try that :
sh script.sh listofip
#!/bin/bash
echo "IP ?"
echo -n "(Value and press Enter) :"
read ip
while read line
do
#VARIABLES
file1=$line
mip=$(echo $file1 | awk '{print $1}')
name=$(echo $file1 | awk '{print $2}')
if [ "$mip" = "$ip" ]
then
echo "Machine name is " $name
fi
done < $1
results :
IP ?
(Value and press Enter) :10.200.99.2
Machine name is master2

In Bash 4, I would use an associative array; see http://mywiki.wooledge.org/BashFAQ/006#Associative_Arrays
For older versions of Bash, maybe use a simple wrapper such as
lookup () {
echo "$1" |
awk 'NR==FNR { a[$1] = $2; next }
$1 in a { print a[$1]; exit 0 }
END { exit 1 }' input.txt -
}
This is slightly inelegant in that it requires the file to exist in the current directory. You can embed the mapping file in the script itself, though that requires some modest refactoring (the here document will tie up standard input so you cannot pipe your input to the script which reads it).
lookup () {
awk -v q="$1" '$1 == q { print $2; exit 0 }
END { exit 1 }' <<'________HERE'
10.200.99.1 master1
10.200.99.2 master2
10.200.99.3 master3
10.200.99.4 slave1
10.200.99.5 slave2
10.200.99.6 slave3
________HERE
}

I got a much simpler solution
#!/bin/bash
### GET IP ADDRESS ###
echo "IP Address ?"
echo -n "(Value and press Enter) :"
read ip_address
### Find Hostname matching to IPADDRESS ###
grep $ip_address /etc/hosts | awk '{print $2}'

Related

Bash while read to include if [duplicate]

I have a file which maps IP Address to hostname. Its format is similar to hosts file and contains a list of ipaddress to hostname mapping.
eg.
10.200.99.1 master1
10.200.99.2 master2
10.200.99.3 master3
10.200.99.4 slave1
10.200.99.5 slave2
10.200.99.6 slave3
...
...
...
I would like to obtain hostname from a given ipaddress using bash script.
How can i do so?
You can try that :
sh script.sh listofip
#!/bin/bash
echo "IP ?"
echo -n "(Value and press Enter) :"
read ip
while read line
do
#VARIABLES
file1=$line
mip=$(echo $file1 | awk '{print $1}')
name=$(echo $file1 | awk '{print $2}')
if [ "$mip" = "$ip" ]
then
echo "Machine name is " $name
fi
done < $1
results :
IP ?
(Value and press Enter) :10.200.99.2
Machine name is master2
In Bash 4, I would use an associative array; see http://mywiki.wooledge.org/BashFAQ/006#Associative_Arrays
For older versions of Bash, maybe use a simple wrapper such as
lookup () {
echo "$1" |
awk 'NR==FNR { a[$1] = $2; next }
$1 in a { print a[$1]; exit 0 }
END { exit 1 }' input.txt -
}
This is slightly inelegant in that it requires the file to exist in the current directory. You can embed the mapping file in the script itself, though that requires some modest refactoring (the here document will tie up standard input so you cannot pipe your input to the script which reads it).
lookup () {
awk -v q="$1" '$1 == q { print $2; exit 0 }
END { exit 1 }' <<'________HERE'
10.200.99.1 master1
10.200.99.2 master2
10.200.99.3 master3
10.200.99.4 slave1
10.200.99.5 slave2
10.200.99.6 slave3
________HERE
}
I got a much simpler solution
#!/bin/bash
### GET IP ADDRESS ###
echo "IP Address ?"
echo -n "(Value and press Enter) :"
read ip_address
### Find Hostname matching to IPADDRESS ###
grep $ip_address /etc/hosts | awk '{print $2}'

Get hostname mapped to IP Address from file similar to hosts file using BASH

I have a file similar to hosts file where IP Address is mapped to hostname.
Below is a snapshot of file
20.200.80.15 slave1
20.200.80.16 slave2
20.200.80.17 slave3
20.200.80.18 slave4
20.200.80.19 slave5
20.200.80.20 master1
I would like to retrive Hostname from IP Address from the above file using bash script i.e. if I supply ipaddress as 20.200.80.18 then i should get output as slave4
The script could be something like this:
#!/bin/bash
if [ $# -ne 1 ];then
echo "Usage: myscript.sh IP";
exit 1;
fi;
IP=$1
HOSTS_FILE=/root/hosts_test
grep -F "$IP " "$HOSTS_FILE" | awk '{ print $2 }'
exit 0;
And you call it like:
sh myscript.sh 20.200.80.16
It is important to use the -F option in grep (or use fgrep) so te dots are considered as litterals and as not regex wildcards.
I think something like this would work:
#!/bin/sh
ip=$1
file=$2
grep $ip $file | tr -s ' ' | cut -d ' ' -f2
and running the script like this:
getHost 20.20.20.20 /etc/ipfile

Listing only the missing info that does not match file 1 from file two

File 1 is the /etc/hosts file with an output below
10.0.0.1 router1
10.0.0.2 router2
10.0.0.3 router3
10.0.0.4 router4
file two id a rancid database in /usr/local/rancid/var/devices/router.db with output like below:
router1:cisco:up
router2:cisco:up
I want to be able to run a script that could look for the hostnames only routerx and find which ones have not been added to the router.bd with routerx:cisco:up.
So the output that I am looking for with the above example would be:
print Missing routers
router3
router4
end
Could you assist with something or point me in the right direction?
You can use this awk:
awk -F '[: ]+' 'FNR==NR {a[$1]; next} !($NF in a) {print $NF}' router.db hosts
router3
router4
Explanation:
-F '[: ]+' # Use custom field separator as 1 or more of colon or space
FNR==NR # for first file populate an array `a` with key as $1
next # keep reading 1st file till EOF is reached
!($NF in a) # from 2nd file execute {...} if last fieild in NOT in array a
{print $NF} # print last field from hosts file
Try:
routerdb="/usr/local/rancid/var/devices/router.db"
while read _ router; do
grep -q "^$router:" $routerdb || echo "Missing: $router"
done < /etc/hosts
You can do it in following way:-
awk -F'\t' {'print $2'} /etc/hosts > temp.txt
awk -F':' {'print $2'} /usr/local/rancid/var/devices/router.db > temp1.txt
cat temp.txt | while read a
do
i=`grep -c $a temp1.txt`
if [ $i -eq 0 ]
then
echo $a
fi
done
This will print router3 & router4..
diff is usually a good choice when comparing files. A complete solution could look like this:
#!/bin/bash
ROUTERDB=/usr/local/rancid/var/devices/router.db
HOSTS=/etc/hosts
# use a temporary directory:
DIR=$(mktemp -d)
cd ${DIR}
# write first field of router.db in one file, using : as delimiter:
awk -F: '{ print $1 }' ${ROUTERDB} > routerdb
# write second field of hosts in the other:
awk '{ print $2 }' ${HOSTS} > hosts
# compare the two files, select only lines not in
# router.db, and remove the + sign at the beginning:
echo Missing routers
diff -u routerdb hosts | grep "^+[^+]" | tr -d "+"
echo end
# remove temporary directory:
rm -rf ${DIR}

expand ssh hostname in shell script

I have a couple of hosts configured in ~/.ssh/config, for example:
Host SomeHost
Hostname 10.0.0.3
User SomeUser
I'm trying to get the hostname part (10.0.0.3) as a variable from inside a shell script (the %h variable).
Is it somehow possible?
host2ip() {
awk -v host="$1" '
$1 == "Host" && $2 == host {have_host = 1}
have_host && $1 == "Hostname" {print $2; exit}
' ~/.ssh/config
}
ip=$(host2ip SomeHost)
echo $ip
10.0.0.3

Replacing IP with server name in fping output

I have a txt with a list of IP that I would like to check using fping, and then translate IP into name.
My file (hosts.txt) looks like this:
192.168.1.1 serverA
192.168.1.2 serverB
192.168.1.3 serverC
and this is the script I have written:
#! /bin/bash
N_Hosts=$(wc hosts.txt | awk {'print $1'})
typeset Nodos[$N_Hosts]
i=0;
while read line
do
Nodos[$i]=$(echo $line | awk {'print $1'})
i=$i+1
done < hosts.txt
comando="fping "
comandoCompleto=$comando${Nodos[*]}
$comandoCompleto | sed 's/is alive/OK/g' | sed 's/is unreachable/down/g'
Its output is like:
192.168.1.1 OK
192.168.1.2 down
192.168.1.3 OK
And I would like it to be:
serverA OK
serverB down
serverC OK
Is it possible to change the output using sed or awk?
If you have two files, your hosts.txt and output.txt (output from script) then you can do:
awk 'NR==FNR{a[$1]=$2;next}{$1=a[$1]}1' hosts.txt output.txt
Entirely in awk (I think this requires gawk)
gawk '
{
name[$1] = $2
ips = ips " " $1
}
END {
while ((("fping" ips) | getline) != 0) {
if ($3 == "alive")
print name[$1] " OK"
else if ($3 == "unreachable")
print name[$1] " down"
}
}
' hosts.txt
or entirely with bash version 4
declare -a ips
declare -A names
while read ip name; do
ips+=($ip)
names[$ip]=$name
done < hosts.txt
fping "${ips[#]}" |
while read ip _ status; do
case $status in
alive) echo ${names[$ip]} OK ;;
unreachable) echo ${names[$ip]} down ;;
esac
done
GNU sed
sed -r 's#(\S+)\s+(\S+)#/\1/s/(\\S+)\\s+(\\S+)/\2 \\2/#' hosts.txt|sed -rf - output.txt
..output:
serverA OK
serverB down
serverC OK
It sounds like all you need is:
while read ip name
do
fping "$ip" |
awk -v n="$name" '{print n, (/alive/?"OK":"down")}'
done < hosts.txt

Resources