In a shell script how to validate if a given host name belongs to localhostname family - bash

In a shell script how to validate if a given host name is localhost
for example :-
localhost
127.0.0.1
myhostname.com
::1
all belong to same machine name, Is there any way to identify that a given host name belongs to localhostname family

Usually all local host names are in /etc/hosts file:
grep -c machine_name /etc/hosts
if the machine name is among the localhost the command above returns 1 or greater, otherwise is 0.
for example:
grep -c myhostname.com /etc/hosts
1
grep -c google.com /etc/hosts
0
Not sure if this is exactly you're looking for but I hope it will help.
Beware of partial match, for example if you have 'myhost' in /etc/hosts grep -c host will return 1 as well. In this case you'll need to use regular expressions or parse /etc/hosts file with cut, awk and similar tools. Or use the following command:
grep -c '\bmachine name\b'
To skip the comments use the command below:
grep -v '^#.*' /etc/hosts | grep -c machine_name
so full command is
grep -v '^#.*' /etc/hosts | grep -c '\bmachine_name\b'

You could check
sysctl kernel.hostname
i.e
sysctl kernel.hostname | grep -c "my_hostname"

I use the following to check whether a supplied hostname is the same as localhost:
hostname_ip(){
host "$1" | sed -e 's/.* \([^ ]*[^ .]\)\.*$/\1/'
}
normalize_hostname(){
local normalized="$1"
grep -q "^\(\([0-9]{1,3}\)\.\)\{3\}\([0-9]{1,3}\)$" <<< "$normalized" || normalized="$(hostname_ip "$normalized")"
normalized="$(hostname_ip "$normalized")"
echo "$normalized"
}
myname="$(normalize_hostname "$(hostname)")"
argname="$(normalize_hostname "$1")"
if [[ "$myname" == "$argname" || "$argname" == "localhost" ]]; then
...
First, normalize the supplied parameter into format set by host utility by running it twice. If IP address is supplied -- checked by regex -- run it only once.
Then compare the value to normalized value of hostname utility or to string "localhost".

Related

Cron job creates empty files

I want to preface that I am a newbie that picked up shell scripting 2 weeks ago.
Hey guys I need help with something, hope someone can point me in the right direction. I have a script that works when I run it from the command line but every time I run it with a crontab, the output is a few empty files. Does anyone know why?
That's the code down there
#!/bin/bash
#Provide an IP address as an argument to use nmap
#make sure to add the full range with (0-225 or 0/24) at the end
IPADDRESS=$(hostname -I | awk '{print $1}')
network-scan(){
if [ $1 ]
then
sudo nmap -sn $1
else
sudo nmap -sn 192.168.1.0-255
fi
}
#Scan the whole network and only prints the IP addresses minus your own
#Sends the IP addresses to a file
network-scan | grep -i 'Nmap scan report' | \
sed 's/\ /\n/g'|sed 's/(//g'|sed 's/)//g' | \
grep '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -v ${IPADDRESS} > ip_addresses
#Scan the whole network and only prints the MAC addresses
#Sends the MAC addresses to a file
network-scan | grep -i 'MAC Address:' | \
awk '{print $3}' > mac_addresses
#Put the IP and MAC addresses in the same file
paste ip_addresses mac_addresses | \
column -s $'\t' -t > "scan_$(date +%d-%m-%Y_%H:%M:%S)"
#Notify that a file with the IP and MAC addresses has been created on the Desktop
echo "A file containing the results of the scan has been created on the Desktop"
exit 0
You are using
network-scan | grep
without passing any parameter.
Hence network-scan function always using
sudo nmap -sn 192.168.1.0-255
when you run it from command line are you passing any parameter ?
echo $IPADDRESS inside the script when executing at cron and at command line for debugging.
network-scan | grep -i 'Nmap scan report' | \
sed 's/\ /\n/g'|sed 's/(//g'|sed 's/)//g' | \
grep '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -v ${IPADDRESS}
Since you are obtaining empty output, validate each command and append(test) each OR operators to know where it is removing required output.

check-mk check if hostname and/or ip already exist

we got a script that inserts new hosts in check_mk via curl
#!/bin/bash
cat file.conf | while read line
do
HOSTNAME=$(echo $line | cut -d '|' -f1)
IP=$(echo $line | cut -d '|' -f2)
curl "http://myserver/mysite/check_mk/webapi.py?action=add_host&_username=automation&_secret=myautomationsecret" -d 'request={"hostname":"'"$HOSTNAME"'","folder":"ansible","attributes":{"ipaddress":"'"$IP"'","site":"mysite","tag_agent":"cmk-agent"}}'
done
the file "file.conf" is an already processed file from an nmap scan with xmlstarlet, this file does not always have the hostname, therefore the ip address was used as hostname
the file.conf looks like this
192.168.30.1|192.168.30.1|os
_gateway|192.168.30.2|Linux 2.6.18 - 2.6.22
...
so for some hosts the ip address was passed once as hostname and logically as ip. now it is so that an employee enters the correct hostname and deletes the ip from the field hostname
if the above mentioned script is executed again, it will create the host again with the ip as hostname (because no hostname was specified), so now we have the host 2x in check_mk 1x with the manually added hostname and once with the ip as hostname
all other hosts where the hostname was already recognized correctly by nmap from start on were not taken over like it should be
we now need a function that asks for the ip address of the hostname before the script is executed and if it is already there the host should not be created again
with curl you can only get the hosts
curl "http://myserver/mysite/check_mk/webapi.py?action=get_all_hosts&_username=automation&_secret=myautomationsecret"
First you will need "jq", so apt-get install jq. ( is for reading json file by bash )
FILE="filename"
getHost="http://myserver/mysite/check_mk/webapi.py?action=get_all_host&_username=automation&_secret=myautomationsecret"
while IFS='|' read -r host ip description
do
checkHost=$( curl -s "$getHost" |
jq -r '.result | keys[] as $k | "\(.[$k] | .attributes | select(.ipaddress=="'$ip'") | .ipaddress )"' | uniq )
if [ "$checkHost" != "$ip" ]
then
# here you already know that this ip ( $ip ) not exist in check_mk
# put your curl command with add_host action here
echo "Hostname: $ip added to check_mk"
else
echo "Hostname: $ip is already exist in check_mk"
fi
done <$FILE
now we have another problem: i have to include the OS directly. this already works with the same add_host so far, i just had to include another attribute
curl "http://myserver/mysite/check_mk/webapi.py?action=add_host&_username=automation&_secret=myautomationsecret" -d 'request={"hostname":"'"$HOSTNAME"'","folder":"ansible","attributes":{"ipaddress":"'"$IP"'","tag_os": "'"$OS"'","site":"mysite","tag_agent":"cmk-agent"}}'
but it is so that you have to insert OS names manually into the checkmk interface, there is a special tab where you can define them
this was already done with the OS Linux, Windows and LCOS
but now it is so that the nmap scan does not have an os included everywhere, so the file.conf looks like this from time to time:
host1|192.168.30.25|Windows
host2|192.168.30.90|Linux
host3|192.168.30.110|Linux
host4|192.168.30.111|Linux
192.168.30.130|192.168.30.130|
192.168.30.131|192.168.30.131|Android
192.168.30.155|192.168.30.155|Linux
192.168.30.157|192.168.30.157|
you can see that at hosts the os is completely missing or that there is something like android
we now want the hosts that do NOT have linux, windows or lcos to have "empty" as tag_os
but the curl command gives an error for hosts with empty os and does not create them
{"result": "Check_MK exception: Unknown tag ", "result_code": 1}{"result": "Check_MK exception: No such host", "result_code": 1}

Bash grep file for string and use each as a variable in another commands

In HA configuration I am checking periodically for VIP address on eth0, (lets call it 2.2.2.2). If it is up, then I need to bring up another group of IP address defined for eth0 in /etc/network/interfaces configuration file:
up ip addr add **1.2.3.34** dev $IFACE
up ip addr add **1.2.3.40** dev $IFACE
up ip addr add **1.2.3.48** dev $IFACE
and pass each IP only to another group of commands:
ip a a **1.2.3.34/32** dev eth0
ip a a **1.2.3.40/32** dev eth0
ip a a **1.2.3.48/32** dev eth0
What I've done so far is:
#!/bin/bash
STATUS=$(ip a s eth0 | grep inet | awk '{print $2}' | sed 's/addr://')
if ip a s eth0 | grep inet | awk '{print $2}' | sed 's/addr://' | grep 2.2.2.2/27 ; then
cat /etc/network/interfaces | grep -o "up ip addr add [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" > /tmp/ext_ip.txt
Now I need help how to pass each line to another command mentioned above (ip a a 1.2.3...), but have no idea how to do this properly.
Optionally I'd like to revert operation if VIP is not present in the system - in case if primary HA host will go offline.
One way to achieve this would be to parse all IP addresses into an array and use a for loop to assign them to the interface:
#!/bin/bash
IFACE='eth0'
VIP='192.168.0.1'
IFACES_FILE='/etc/network/interfaces'
STATUS=$( ip address show "$IFACE" | grep -o "$VIP" )
if [ ! -z "$STATUS" ]; then
ip_addresses=( $( grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' "$IFACES_FILE" ) )
for ip in "${ip_addresses[#]}"; do
ip address add "$ip" dev "$IFACE"
done
fi
This is a simplified example. You may want to add more checks, add some logging messages to provide output useful for debugging. Also, depending on your server configuration some commands may not work without sudo.
Thanks Andrii L. I've improved your solution to:
#!/bin/bash
IFACE='eth0'
VIP='2.2.2.2'
IFACES_FILE='/etc/network/interfaces'
STATUS=$( ip address show "$IFACE" | grep -o "$VIP" )
if [ ! -z "$STATUS" ]; then
ip_addresses=( $( grep -o 'up ip addr add [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' "$IFACES_FILE" | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' ) )
for ip in "${ip_addresses[#]}"; do
ip address add "$ip"/32 dev "$IFACE"
done
else
for ip in "${ip_addresses[#]}"; do
ip address del "$ip"/32 dev "$IFACE"
done
fi
otherwise it is trying to add all IPs and broadcasts found in /etc/network/interfaces file.

use tcpkill command from an ip list

I have got an ip list in a file called ips:
ip1
ip2
I want to tcpkill from this list. I cannot do it from tcpkill command options. I need a script which will write :
tcpkill -i eth0 -9 host ip1 or host ip2
the list can grow in time.
the only thing I know is that I will need a loop to read the list:
for IP in $(cat list) ; do
echo "tcpkill -i eth0 -9 host $IP " (for
the first element of the list)
echo "or host $IP" (for the rest of
the list).
So my questions are:
1. what would be the right syntax for this purpose?
2. Is there a completely different way of doing this?
Any idea folks ?!
thank you very much.
This single line command would append the IP list to tcpkill command to form the complete command:
tcpkill -i eth0 -9 host $(cat list | xargs | sed 's/ / or host /g')
You can put this command after echo to see how the command gets formed.
echo tcpkill -i eth0 -9 host $(cat list | xargs | sed 's/ / or host /g')

Shell script to make directories and subdirectories with variable names

I'm trying to create script to be run by cron to create multiple folders with subfolders.
DATE=`date +%Y-%m-%d`
IP_ADDR=`ifconfig | grep -v '127.0.0.1' | sed -n 's/.*inet addr:\([0-9.]\+\)\s.*/\1/p'`
/bin/mkdir -p /mnt/db-backup/12/$DATE/$IP_ADDR/
If i run this script manually everything is created as expected. When script is ran by cron subdirectory $IP_ADDR is not created and there is no errors.
I suspect that /sbin is not part of the PATH for the environment that the cron job runs under. You should specify the full path for the ifconfig command:
IP_ADDR=$(/sbin/ifconfig | grep -v '127.0.0.1' | sed -n 's/.*inet addr:\([0-9.]\+\)\s.*/\1/p')
It's also better practice (in general) to use $() for command substitution.
Try to use debug mode :
set -x
DATE=`date +%Y-%m-%d`
IP_ADDR=`ifconfig | grep -v '127.0.0.1' | sed -n 's/.*inet addr:\([0-9.]\+\)\s.*/\1/p'`
/bin/mkdir -p /mnt/db-backup/12/$DATE/$IP_ADDR/
set +x
Then, redirect the output of your cron to a file and have a look, you should find useful information in it.
You are not far off, but there are several ordering caveats that could cause problems. Many systems have different formats for the ifconfig output line. Some with inet xxx.xxx.xxx.xxx, others with inet addr:xxx.xxx.xxx.xxx. (those are the two most common). You may also need to handle the case where there are multiple wired inet interfaces (2+ NICs in the box). However, if you have only 1 NIC, you could try the following to handle the common ifconfig formats:
DATE=`date +%Y-%m-%d`
IP_ADDR=$(ifconfig |
grep -v '127.0.0.1' |
grep -E 'inet[ ](addr:)*[0-9]{1,3}([.][0-9]{1,3}){3}' |
sed -e 's/^.*inet \(addr:\)*//' -e 's/ .*$//')
/bin/mkdir -p /mnt/db-backup/12/$DATE/$IP_ADDR/
or with IP_ADDR written as one line:
IP_ADDR=$(ifconfig | grep -v '127.0.0.1' | grep -E 'inet[ ](addr:)*[0-9]{1,3}([.][0-9]{1,3}){3}' | sed -e 's/^.*inet \(addr:\)*//' -e 's/ .*$//')

Resources