expand ssh hostname in shell script - shell

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

Related

BASH: ssh access variable result on remote host

How do I make a variable accessible on a remote computer via ssh?
I have a bash array containing n IP addresses for this specific instance I want to send the "result" of the first element in the array to the remote machine for further use.
#!/bin/bash
servers=(192.168.130.252 10.10.10.10 12.12.12.12)
echo "Before ssh: ${servers[0]}"
ssh ubuntu#"${servers[0]}" /bin/bash<<"EOF"
echo "$(hostname -I | awk '{print $1}')"
echo "After ssh: ${servers[0]}"
# MORE COMMAND HERE
EOF
exit 0
#Output
Before ssh: 192.168.130.252
192.168.130.252
After ssh:
Because you have used quotes in "EOF", ${servers[0]} gets expanded in remote shell, so to an empty string as array servers is not defined.
One way around is :
#!/bin/bash
servers=(192.168.130.252 10.10.10.10 12.12.12.12)
echo "Before ssh: ${servers[0]}"
ssh ubuntu#"${servers[0]}" CURRENT_HOST="${servers[0]}" /bin/bash<<"EOF"
echo "$(hostname -I | awk '{print $1}')"
echo "After ssh: $CURRENT_HOST"
# MORE COMMAND HERE
EOF
exit 0
Just found a way to send the whole array to remote shell:
#!/bin/bash
servers=(192.168.130.252 10.10.10.10 12.12.12.12)
echo "Before ssh: ${servers[0]}"
{ declare -p servers
cat << "EOF"
echo "$(hostname -I | awk '{print $1}')"
echo "After ssh: ${servers[0]}"
# MORE COMMAND HERE
EOF
} | ssh ubuntu#"${servers[0]}" /bin/bash

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}'

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

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

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