how to distinguish the domain from a subdomain - bash

i have a problem with script.
At my work i often have to check PTR of domain, MX records and similar data. I did the most of the script, but the problem appears when i do something likethis is subdomain
e-learning.go4progress.pl
this is domain but second level?
simple.com.pl
Now in my script there is something like: if i don't put www, it adds and does
dig www.e-learning.go4progress.pl
dig e-learning.go4progress.pl
dig go4progress.pl
he counts dots and subtracts 1, but problem is when domain looks like
simple.com.pl
because script make dig too for
com.pl
I don't check many domain which contains com.pl, co.uk, gov.pl. I've got an idea to make array and compare this what i put in script with array, when it finds in string component of array he subtracts 2 instead 1 ;)
I paste a part of script to better understand me why he substracks 1.
url="`echo $1 | sed 's~http[s]*://~~g' | sed 's./$..' | awk '!/^www/ {$0="www." $0}1'`"
ii=1
dots="`echo $url | grep -o "\." | wc -l`"
while [ $ii -le $dots] ; do
cut="`echo $url | cut -d "." -f$ii-9`"
ip="`dig +short $cut`"
host="`dig -x $ip +short`"
if [[ -z "$host" ]]; then
host="No PTR"
fi
echo "strona: $cut Host: $host"
ii=$[ii + 1]
Maybe you have diffrent idea how to help with my problem.
Second question is how to distinguish subdomain from domain.
I need compare mx records of subdomain(when the url contains subdomain) and mx records top level domain.
I waiting for your response ;)

My solution to find the domain as registered with the registrar:
wget https://raw.githubusercontent.com/gavingmiller/second-level-domains/master/SLDs.csv
DOMAIN="www.e-learning.go4progress.co.uk";
KEEPPARTS=2;
TWOLEVELS=$( /bin/echo "${DOMAIN}" | /usr/bin/rev | /usr/bin/cut -d "." --output-delimiter=".\\" -f 1-2 | /usr/bin/rev );
if /bin/grep -P ",\.${TWOLEVELS}" SLDs.csv >/dev/null; then
KEEPPARTS=3;
fi
DOMAIN=$( /bin/echo "${DOMAIN}" | /usr/bin/rev | /usr/bin/cut -d "." -f "1-${KEEPPARTS}" | /usr/bin/rev );
echo "${DOMAIN}"
Thanks to https://github.com/gavingmiller/second-level-domains and https://github.com/medialize/URI.js/issues/17#issuecomment-3976617

Related

display grid of data in bash

would like to get an opinion on how best to do this in bash, thank you
for x number of servers, each has it's own list of replication agreements and their status.. it's easy to run a few commands and get this data, ex;
get servers, output (setting/variable in/from a local config file);
. ./ldap-config ; echo "$MASTER $REPLICAS"
dc1-server1 dc1-server2 dc2-server1 dc2-server2 dc3...
for dc1-server1, get agreements, output;
ipa-replica-manage -p $(cat ~/.dspw) list -v $SERVER.$DOMAIN | grep ': replica' | sed 's/: replica//'
dc2-server1
dc3-server1
dc4-server1
for dc1-server1, get agreement status codes, output;
ipa-replica-manage -p $(cat ~/.dspw) list -v $SERVER.$DOMAIN | grep 'status: Error (' | sed -e 's/.*status: Error (//' -e 's/).*//'
0
0
18
so output would be several columns based on the 'get servers' list with each 'replica: status' under each server, for that server
looking to achieve something like;
dc2-server1: 0 dc2-server2: 0 dc1-server1: 0 ...
dc3-server1: 0 dc3-server2: 18 dc3-server1: 13 ...
dc4-server1: 18 dc4-server2: 0 dc4-server1: 0 ...
Generally eval is considered evil. Nevertheless, I'm going to use it.
paste is handy for printing files side-by-side.
Bash process substitutions can be used where you'd use a filename.
So, I'm going to dynamically build up a paste command and then eval it
I'm going to use get.sh as a placeholder for your mystery commands.
cmd="paste"
while read -ra servers; do
for server in "${servers[#]}"; do
cmd+=" <(./get.sh \"$server\" agreements | sed 's/\$/:/')"
cmd+=" <(./get.sh \"$server\" status)"
done
done < <(./get.sh servers)
eval "$cmd" | column -t

Write a linux script to find errors occurred in a log file during the last hour and send mail if errors found

I want to find errors which have occurred in log file during the last hour. This is because I plan to schedule the script every hour in cron. I want to search for multiple error patterns and want to send mail if any one of those error patterns have been found during the last hour. Can someone please help me?
#Script which I tried to write is below
#!/bin/bash
SUBJECT="Critical errors found on $HOSTNAME"
TO="abc#example.com"
FNAME="/var/log/log4j/test.log"
PATTERN1="StackOverflow"
PATTERN2="OutOfMemory"
if [ ! -f stack.txt ]; then
touch stack.txt
fi
if [ ! -f comp_stack.txt ]; then
touch comp_stack.txt
fi
#first 19 bytes of log entry represents date/timestamp
cat stack.txt > comp_stack.txt
first_date="$(head -c19 comp_stack.txt)"
echo "first date is $first_date"
tac "$FNAME" | grep -m 1 -i "$PATTERN1\|$PATTERN2" > stack.txt
next_date="$(head -c19 stack.txt)"
echo "next date is $next_date"
if [ -s stack.txt ] && [ "$next_date" != "$first_date" ]; then
echo "dates not equal and file exists"
mail -s "$SUBJECT" "$TO" < stack.txt
fi
My script is creating 2 files stack.txt and comp_stack.txt if they don't exist.
It is supposed to search for pattern1 and pattern2 during last hour (I used "-m 1" to achieve this, but it gives me only 1 pattern in the output even if there are multiple patterns which match the error).
As I don't want the script to report same error multiple times, I am saving and comparing dates in my .txt files. So that error will be reported only if error timestamp is different from what was previously saved in the .txt file.
I used "tac" to search my log files from bottom to top as my log files are huge and I want to save time.
I am new to linux and scripting. Please help me write a working script.
Here is one line sample of my log file -
2020-09-01 01:27:16,500 | DEBUG | WebContainer : 17 | | | com.hertz.rates.common.utils.jdbc.RecordCallableStatement | DB Response: Activate/Cancel | 65 | READY | 2020-09-01 01:27:16,500 | DEBUG | WebContainer : 17 | | | com.hertz.rates.common.utils.jdbc.RecordCallableStatement | DB Response: Activate/Cancel | 65 |
Try this
mail="abc#example.com" # email address
subj="Critical errors found on $HOSTNAME" # email subject
logf="/var/log/log4j/test.log" # log file name
errs="StackOverflow|OutOfMemory" # define errors to check
printf -v time '%(%Y-%m-%d %H:)T' # get time template
check=$(grep "$time" "$logf" | grep "$errs" "$logf")
[[ $check ]] && mail -s "$subj" "$mail" <<< "$check"

BASH search for multiple IP's in table

This is a continuation of a script I got help on a few weeks ago. I got everything working, unfortunately the scenario has changed a bit and I'm under a little pressure to get this up and running so I was hoping someone here would help me quickly modify this script.
Here are the basics. The purpose of the script is to recapture a specific floating IP. Due to system limitations, the only way to do this currently is by kinda playing the lottery... The script requests a pool of floating IP's and puts them in a table that looks like this:
+------------+-----------+----------+---------------+
| Ip | Server Id | Fixed Ip | Pool |
+------------+-----------+----------+---------------+
| 10.10.10.1 | | - | floating-pool |
| 10.10.10.2 | | - | floating-pool |
| 10.10.10.3 | | - | floating-pool |
| 10.10.10.4 | | - | floating-pool |
| 10.10.10.5 | | - | floating-pool |
+------------+-----------+----------+---------------+
The script then checks to see if the floating IP we are looking for is in that table, ie has been captured. If not, the script returns all IP's back to the pool and tries again. If the address we are looking for has been captured, then the script drops all other IP's and terminates.
The current version of this script works great to capture a single IP, but now we need it to capture several IP's. Here is the old single IP version:
#!/bin/bash
# Floating IP Reclaimer
################# CONFIG ##################
float="10.10.10.3"
tenantid="blah"
###########################################
# Start
clear
loop=true
if ! [ "$tenantid" = "$OS_TENANT_ID" ]; then
echo "ERROR - Be sure you have sourced the proper tenant ID!"
else
l=1
while $loop; do
printf "Floating IP Reclaimer\n\n"
printf "Requesting address block...\n"
for ((i=1;i<=5;i++));
do
nova floating-ip-create floating-pool > /dev/null 2>&1
done
printf "Checking for matches...\n"
nova floating-ip-list > /tmp/block
while read garbage1 ip garbage2;
do
if [ "$ip" != "$float" ]; then
printf "Releasing $ip\n"
nova floating-ip-delete "$ip" > /dev/null 2>&1
else
loop=false
fi
done < <(tail -n +4 /tmp/block | head -n -1)
printf "\nFloating IP blocks searched: "$l
l=$((l+1))
clear
done
printf "\nFloating IP reclaimed!\n\n"
fi
Thank you everyone for the help. I'm working on a solution as we speak. Unfortunately, sometimes I don't work too well under pressure.
Thanks!
Try this on for size (it hasn't been tested). I know it's not bash, but it should get the job done
#!/usr/bin/python
import os,time
import novaclient.client as nvclient
class FloatingIpManager():
def __init__(self,desired_addresses=[],sleep=5):
self.ips = desired_addresses
self.nova = get_nova_client()
self.sleep = sleep
def get_nova_client(self,env=os.environ):
d = {}
d['username'] = env['username']
d['api_key'] = env['password']
d['auth_url'] = env['auth_url']
d['project_id'] = env['tenant_name']
return nvclient.Client('2',**d)
def get_float(self,address=None,pool=None):
while True:
try:
flip = self.nova.floating_ips.create(pool)
if flip.ip in self.ips or address == None:
return True
else:
self.release_float(flip)
except Exception as e:
print e
time.sleep(self.sleep)
def release_float(self,flip):
return self.nova.floating_ips.delete(flip)
def reclaim_all(self,addresses=None):
if addresses == None:
addresses = self.ips
for i in self.ips:
get_float(i)
if __name__ == '__main__':
nova = get_nova_client()
reclaimer = FloatingIpManager(['192.168.100.1'])
reclaimer.reclaim_all()
Your bash answer. Call it with the IP's you want as arguments, like "reclaimer 192.168.1.1 192.168.1.2 192.168.1.3"
#!/bin/bash
# Floating IP Reclaimer
################# CONFIG ##################
#float="10.10.10.3"
tenantid="blah"
###########################################
# Start
clear
loop=true
let count=$#-1
if ! [ "$tenantid" = "$OS_TENANT_ID" ]; then
echo "ERROR - Be sure you have sourced the proper tenant ID!"
else
l=1
while $loop; do
printf "Floating IP Reclaimer\n\n"
printf "Requesting address block...\n"
for ((i=1;i<=5;i++));
do
nova floating-ip-create floating-pool > /dev/null 2>&1
done
printf "Checking for matches...\n"
nova floating-ip-list > /tmp/block
while read garbage1 ip garbage2;
do
for float in $#; do
if [ "$ip" != "$float" ]; then
printf "Releasing $ip\n"
found=false
else
let i=i+1
continue 2
fi
done
nova floating-ip-delete "$ip" > /dev/null 2>&1
done < <(tail -n +4 /tmp/block | head -n -1)
printf "\nFloating IP blocks searched: "$l
l=$((l+1))
clear
if [ i -eq count ]; then
loop=false
fi
done
printf "\nFloating IP reclaimed!\n\n"
fi

Nagios Plugin not Working

I'm having an issue when i try to port my bash script to nagios.The scripts works fine when I run on console, but when I run it from Nagios i get the msg "(null)" - In the nagios debug log I see that it parse the script well but it returns the error msg..
I'm not very good at scripting so i guess i'll need some help
The objective of the script is to check *.ears version from some servers, md5 them and compare the output to see if the version matches or not.
To do that, i have a json on these servers that prints the name of the *.ear and his md5.
so.. The first part of the script gets that info from the json with curl and stores just the md5 number on a .tempfile , then it compares both temp files and if they match i got the $STATE_OK msg. If they dont , it creates a .datetmp file with the date ( the objective of this is to print a message after 48hs of inconsistence). Then, i make a diff of the .datetmp file and the days i wanna check if the result is less than 48hrs it prints the $STATE_WAR, if the result is more than 48 hrs it Prints the $STATE_CRI
The sintaxis of the script is " $ sh script.sh nameoftheear.ear server1 server2 "
Thanks in advance
#/bin/bash
#Variables For Nagios
cont=$1
bas1=$2
bas2=$3
## Here you set the servers hostname
svr1= curl -s "http://$bas1.domain.com:7877/apps.json" | grep -Po '"EAR File":.*? [^\\]",' | grep $cont | awk '{ print $5 }' > .$cont-tmpsvr1
svr2= curl -s "http://$bas2.domain.com:7877/apps.json" | grep -Po '"EAR File":.*? [^\\]",' | grep $cont | awk '{ print $5 }' > .$cont-tmpsvr2
file1=.$cont-tmpsvr1
file2=.$cont-tmpsvr2
md51=$(head -n 1 .$cont-tmpsvr1)
md52=$(head -n 1 .$cont-tmpsvr2)
datenow=$(date +%s)
#Error Msg
ERR_WAR="Not updated $bas1: $cont $md51 --- $bas2: $cont $md52 "
ERR_CRI="48 hs un-updated $bas1: $cont $md51 --- $bas2: $cont $md52 "
OK_MSG="Is up to date $bas1: $cont $md51 --- $bas2: $cont $md52 "
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
##Matching md5 Files
if cmp -s "$file1" "$file2"
then
echo $STATE_OK
echo $OK_MSG
# I do the rm to delete the date tmp file so i can get the $STATE_OK or $STATE_WARNING
rm .$cont-datetmp
exit 0
elif
echo $datenow >> .$cont-datetmp
#Vars to set modification date
datetmp=$(head -n 1 .$cont-datetmp)
diffdate=$(( ($datenow - $datetmp) /60 ))
#This var is to set the time of the critical ERR
days=$((48*60))
[ $diffdate -lt $days ]
then
echo $STATE_WARNING
echo $ERR_WAR
exit 1
else
echo $STATE_CRITICAL
echo $ERR_CRI
exit 2
fi
I am guessing some kind of permission problem - more specifically I don't think the nagios user can write to it's own home directory. You either fix those permissions or write to a file in /tmp (and consider using mktemp?).
...but ideally you'd skip writing all those files, as far as I can see all of those comparisons etc could be kept in memory.
UPDATE
Looked at your script again - I see some obvious errors you can look into:
You are printing out the exit value before you print the message.
You print the exit value rather than exit with the exit value.
...so this:
echo $STATE_WARNING
echo $ERR_WAR
exit 1
Should rather be:
echo $ERR_WAR
exit $STATE_WARNING
Also I am wondering if this is really the script or if you missed something when pasting. There seems to be missing an 'if' and also a superfluous line break in your last piece of code? Should rather be:
if [ $diffdate -lt $days ]
then
...
else
...
fi

syntax error: operand expected (error token is ">= 75 ")

#!/bin/bash
CURRENT=$(df -h / | grep / | awk '{ print $4}')
THRESHOLD=75
if (( "$CURRENT" >= "$THRESHOLD" )); then
mail -s "CENTOS-6 localhost 10.10.1.238 Disk Space Alert" sss#abc.net << EOF
Your root partition remaining free space is critically low. Used: $CURRENT%
EOF
fi
I got the following error when i run the script, syntax error: operand expected (error token is ">= 75 ")
It's because CURRENT will contain a percent sign, so it won't be a valid operand for the comparison operation.
You can remove the last character like this :
CURRENT=${CURRENT%?};
Also make sure that df -h / | grep / | awk '{ print $4}' is correctly returning the usage ratio, on most systems you have to use print $5.
A couple of things:
you don't need grep at all, awk is quite capable of doing it's own regex stuff.
if you search for / in the df output, you'll probably get most lines as most mounts have a / somewhere in them. If you just want the root mountpoint, you can use <space>/$.
Check that 4 is the correct field number, on my box it's 5.
In any case, that field is of the form 55% which will not be considered numeric. You can use gsub to get rid of it.
With that in mind, the following snippet can be used to get the percentage:
df -h | awk '$0 ~ / \/$/ { gsub("%","",$5); print $5 }'
And, just as an aside, I'm not that big a fan of here-docs in shell scripts since it either (1) screws up my nicely indented files; or (2) makes me burn half an hour while I try to remember the various syntax options which will allow indented EOF strings :-)
I prefer something like:
(
echo Your root partition remaining free space is critically low: Used: ${CURRENT}%
) | mail -s "CENTOS-6 localhost 10.10.1.238 Disk Space Alert" sss#abc.net
Especially since that means I can put arbitrarily complex commands in the sub-shell to generate whatever info I want in the mail message (rather than just simple text substitutions).
So, bottom line, I'd be looking at something more like:
#!/usr/bin/env bash
# Config section.
LIMIT=75
# Code section.
CURR=$(df -h | awk '$0 ~ / \/$/ { gsub("%","",$5); print $5 }')
if [[ ${CURR} -ge ${LIMIT} ]] ; then
(
echo "Your root partition remaining free space is critically low: Used: ${CURR}%"
) | mail -s "CENTOS-6 localhost 10.10.1.238 Disk Space Alert" sss#abc.net
fi
Just try:
CURRENT=$(df -h |awk '{print $4}' |sort -n |tail -n1 |sed 's/%//g')
THRESHOLD=90
if [ $THRESHOLD -gt $CURRENT ]

Resources