Output the file in way we wanted - bash

I have ssh config file which contains so many servers from google,aws and some remote servers.I wanted to have a bash function that will output only the Host and the HostName of the server so I dont have to remember there public DNS to check my webapps.
Sample Server Config in my ssh config looks like this
Host aws_server
User rand
HostName 65.2.25.152
Port 8000
IdentityFile PEM PATH
ServerAliveInterval 120
ServerAliveCountMax 30
I want the output like
aws_server 65.2.25.152
for all the servers

Using sed
sed '/^Host/{s/[^ ]* //;:1;N;s/\n.*HostName */\t/;t2;b1;:2;p};d' file
aws_server 65.2.25.152
Modified version that's more robust for multiple hosts,missing HostNames
sed ':1;s/\(.*\n\|^\)Host *//;N;s/\n.*HostName */\t/;t2;$!{b1;:2;p};d' file

using awk
awk '{if($1=="Host")k=$2;if($1=="HostName")printf("%s\t%s\n",k,$2)}' file

I would use awk for this:
awk '
# Save the host when we see it.
/^Host/ {
host=$2
next
}
# If we have a host and are on a HostName line
host && $1 == "HostName" {
# Print the Host and HostName values
printf "%s"OFS"%s\n", host, $2
host=""
next
}
# If we have a HostName without a Host clear the host (should not happen but just to be safe)
$1 == "HostName" {
host=""
}
' .ssh/config

Related

Bash complete with "#"-sign

I am trying to create an autocomplete script for scp.
The script reads the user and hostname from my .ssh/config file
My .ssh/config file looks like:
Host host1
HostName host1
User userA
port 22
Host host2
HostName host2
User userB
port 22
Host host3
HostName host3
User userB
port 22
My .autocomplete_scp.sh file is:
# SSH
function _scp_completion() {
pcregrep -o -M 'HostName [a-zA-Z.]+[\n\t\s]+User [a-zA-Z]+'
$HOME/.ssh/config | awk 'NR % 2 == 1 { o=$2 ; next } { print $2"#"o}'
}
complete -W "$(_scp_completion)" scp
I source this file in my bashrc.
Now when I type userA and press Tab, the autocomplete function will give me userA#host1. When I type userB and hit Tab, the autocomplete function will give me userB#, but I am not able to get the full string (userB#host2 or userB#host3).
It also doesn't work when I type userA#h and hit the Tab button twice. So it seems to get stuck due to the # sign.
(When I remove the # sign from the _scp_completion function it works fine.)
Any ideas to fix this? Thanks!
The easy way to make it work is to remove '#' from $COMP_WORDBREAKS or Bash would handle # by itself. You can try like this:
COMP_WORDBREAKS=${COMP_WORDBREAKS//#}
complete -W 'userA#host1 userB#host2 userB#host3' scp
According to bash doc:
COMP_WORDBREAKS
The set of characters that the readline library treats as word separators when performing word completion.

Ssh not working when host is taken using grep

When I'm hardcoding i. e.
server1=ip-10.237.40.10-aws-n-myhost
ssh - i /home/<passwordfile> akhil#$server1
It is working,but when I'm greping the host from other file its not working
Eg:
server2=$(grep - e host /home/akhil/configuration. File | awk FS, '{print $2} ' )
echo $server2
ssh - i /home/<passwordfile> akhil#$server2
While printing server 2 is fine, but when it is used in ssh I'm getting a error saying : not known host name.
I want to automate the script with a configuration file so that when ever the cluster changes I could simply change the ip address in configfile instead of changing in all my scripts.
I need help in this.
Thanks

How to create network file based on IP address from file similar to /etc/hosts

I have a file which maps IP address to hostnames. Its format is similar to hosts file and contains a list of IP address 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 create network file (/etc/sysconfig/network) for all the IP address mentioned in the file.
The format of network file is where the hostname is mentioned based on hosts file.
NETWORKING=yes
HOSTNAME=master1
NOZEROCONF=yes
For every IP Address the network file is created in a directory named by IP Address i.e. network/{IPAddress}.
For example for master1 the path of file should be network/10.200.99.1 and for master2 the path should be network/10.200.99.2.
How can i do so?
Till now I have obtained IPAdress by following command echo $(<hosts) | awk '{print $1}' and Hostname by echo $(<hosts) | awk '{print $2}. But this only prints the contents of first line of the hosts file.
Reads ip and hostname from hosts and writes desired output to network/$ip.
while read ip hostname; do
printf '%s\n' "NETWORKING=yes" "HOSTNAME=$hostname" "NOZEROCONF NF=yes" > network/$ip
done < hosts

Mac OS X Bash Hosting Script

After adding a hosting file using etc/hosts on Mac OS X machines manually we found out we needed to remove the current hosts and add a new one. I'm wondering if it's possible to add a hosting file for Mac OS X using Bash.
This is the current state. How do we change the final line or add one to it?
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost Computer_Name
255.255.255.0 broadcasthost
::1 localhost
10.24.82.5 server_name
I guess you are asking how to edit the file from the command line, then
$ sed -i.OLD 's#10\.24\.82\.5 #8.8.8.8 #' /etc/hosts
The -i option allows sed to edit in-place.
You may need sudo to have write permission to that file.
You can simply use sed to change it, you just need to provide new ip address:
sed 's/^.*\(server_name\)/new_ip_address \1/' file

Puppet - how can I add host entry dynamically reading from linux $hostname

I am using puppet for provisioning to AWS cloud. I am a newbie to this.
My requirement is to add entry into /etc/hosts file of amazon ec2 instance. However at the time of writing puppet, I do not know the actual hostname.
How can I use $HOSTNAME variable in .pp file?
Something like this -
host { '$HOSTNAME':
ip => 'echo $HOSTNAME | tr "-" "." | sed 's/ip.//'',
host_aliases => 'mywebsite',
}
Something like this :
host { $fqdn :
ip => $ipaddress,
host_aliases => 'mywebsite',
}
$fqdn provides fully qualified domain name and $ipaddress provides IP address for the machine. These variables are available if you have facter installed in your system. facter is available at the puppetlab repo. You can install it the same way you installed puppet in your system.
As in the comment, you can also use $hostname to get the short-hostname in place of $fqdn.
Since I wanted the hosts file to be updated before startup script's start gets executed, I did this and it worked for me.
Added this in /etc/init.d/
setup_hostname() {
IPADDR=`echo $HOSTNAME | tr "-" "." | sed 's/ip.//'`
echo "${IPADDR} ${HOSTNAME}" >> /etc/hosts
}
Called setup_hostname from start
case "$1" in
start)
clean
setup_hostname
start
;;

Resources