script to check when a directory is last updated - linux

I am trying to write a script that takes the last update date of a hadoop path subtracts it from current date and sends out an email if the difference is more than a certain number of days (variable).It needs to loop through a pipe delimited config file which has the number of days, table name,hadoop path and email
example of config file
30|db.big_leasing_center|/TST/DL/EDGE_BASE/GFDCP-52478/BIG_LEASING_CENTER/Data/|abcd#gmail.com
2|db.event|/TST/DL/EDGE_BASE/GFDCP-52478/GFDCP01P-ITG_FIN_DB/EVENTS/Data/|cab#gmail.com
below is what i tried
#!/bin/ksh
check_last_refresh() {
DAYS=$1
TABLE=$2
HDP_PATH=$3
EMAIL_DL=$4
last_refresh_date=$(hdfs dfs -ls $HDP_PATH | grep '^-' | awk '{print $6}' | sort -rh | head -1)
echo $last_refresh_date
diff=$(( ( $(date '+%s') - $(date '+%s' -d "$last_refresh_date") ) / 86400 ))
echo $diff
if [ "$diff" -gt "$DAYS" ]; then
echo "HI for $TABLE has an issue" | mail -s "HI for $TABLE has an issue, Please check" -b $EMAIL_DL
fi
return 0
}
cat /data/scratchSpace/bznhd9/CONFIG.txt | while read line; do
DAYS=$(echo $line|awk -F'|' '{print $1}')
TABLE=$(echo $line|awk -F'|' '{print $2}')
HDP_PATH=$(echo $line|awk -F'|' '{print $3}')
EMAIL_DL=$(echo $line|awk -F'|' '{print $4}')
echo $TABLE
r=$(check_last_refresh $DAYS $TABLE $HDP_PATH $EMAIL_DL)
echo $r
done
Please help

Related

Recover network info for each network card in a for loop and do something with it with bash

I created a script that recovers info from a remote VM and generates a second script that creates a new ifcfg-eth* and replaces it in a local copy of the same VM we are migrating (basically the remote VM is in DHCP and we are migrating them in a new location with a static IP and info that we recover from the original VM):
#! /bin/bash
# Version 1.0
# Last review 27/01/2022
# Author Alessandro
# Define variables
RED='\033[0;31m'
NC='\033[0m' # No Color
NCC="\e[0m"
CYAN='\e[96m'
USER='user'
CWD=$(pwd)
# Checks if the IP exists after the script name
if [ -z "$1" ]; then echo -e "${RED}Where is the IP?${NC}" && exit 1; fi
echo -e "${CYAN}Starting...${NCC}"
# Stores the output of of 'script' in the variable $RAW_INPUT
RAW_INPUT=$(ssh -o StrictHostKeyChecking=no $USER#"$1" <<'SCRIPT'
# Script
HOSTNAMEVM=$(hostname -s)
GW=$(/sbin/ip route | awk '/default/ { print $3 }')
INTERFACE1=$(ip link | awk -F: ' $0 !~"lo|vir|wl|^[^1-2]" {print $2;getline}' | awk '{ gsub (" ", "", $0); print}')
IP1=$(ifconfig "${INTERFACE1}" 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://')
SUBNET1=$(/sbin/ifconfig "${INTERFACE1}" | grep Mask | cut -d":" -f4)
INTERFACE2=$(ip link | awk -F: ' $0 !~"lo|vir|wl|^[^3-4]" {print $2;getline}' | awk '{ gsub (" ", "", $0); print}')
IP2=$(ifconfig "${INTERFACE2}" 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://')
SUBNET2=$(/sbin/ifconfig "${INTERFACE2}" | grep Mask | cut -d":" -f4)
echo "Hostname:${HOSTNAMEVM}"
echo "GW:${GW}"
echo "Network-card1:${INTERFACE1}"
echo "${INTERFACE1}_IP1:${IP1}"
echo "SUBNET_1:${SUBNET1}"
echo "Network-card2:${INTERFACE2}"
echo "${INTERFACE2}_IP2:${IP2}"
echo "SUBNET_2:${SUBNET2}"
echo "ENDECA:${ENDECA}"
SCRIPT
)
# Generate the variables for the pre_failover_script parsing the RAW_INPUT variable
VM_NAME=$( echo "${RAW_INPUT}" | awk -F"Hostname:" '/Hostname:/{print $2}')
# Verifies if the executed pre failover script already exists
if [ -f "${CWD}"/executed_pre_"${VM_NAME}".sh ]; then echo -e "${RED}WARNING${NC}:The pre failover script for${NC} ${CYAN}${VM_NAME}${NC} has been already executed!" && exit 1; fi
JOB_ID=$("${CWD}"/list_jobs.sh | grep "${VM_NAME}" | awk -F"mnt/" '/mnt/{print $2}')
# Checks if a job exists for the vm name
if [ -z "${JOB_ID}" ]; then
echo -e "${RED}The job ID for${NC} ${VM_NAME} ${RED}doesn't exist.${NC}";
exit 1;
fi
IP_GATEWAY=$(echo "${RAW_INPUT}" | awk -F"GW:" '/GW:/{print $2}')
INTERFACE_1=$( echo "${RAW_INPUT}" | awk -F"card1:" '/card1:/{print $2}')
IP_1=$( echo "${RAW_INPUT}" | awk -F"IP1:" '/IP1:/{print $2}')
SUB_1=$( echo "${RAW_INPUT}" | awk -F"NET_1:" '/NET_1:/{print $2}')
INTERFACE_2=$( echo "${RAW_INPUT}" | awk -F"card2:" '/card2:/{print $2}')
IP_2=$( echo "${RAW_INPUT}" | awk -F"IP2:" '/IP2:/{print $2}')
SUB_2=$( echo "${RAW_INPUT}" | awk -F"NET_2:" '/NET_2:/{print $2}')
# Prints the value of ENDECA in case the Symbolic Link has been removed
ENDECA=$( echo "${RAW_INPUT}" | awk -F"ENDECA:" '/ENDECA:/{print $2}')
# Removing existing pre_failover_script file for the ECL2 instance in current directory
rm -rf "${CWD}"/pre_failover_script_"${VM_NAME}".sh
# Define pre_failover_script variable
PRE_FAILOVER_SCRIPT_LOCATION="${CWD}"/pre_failover_script_${VM_NAME}.sh
# Generate ifcfg-eth* file based on information gathered above
echo "#! /bin/bash
PATH_TO_JOB_ID=/opt/dbtk/mnt/${JOB_ID}
PATH_TO_UDEV_NET_RULES_FILES=/etc/udev/rules.d
PATH_TO_GATEWAY_FILE=/etc/sysconfig/network
CLOUD_INIT_LOCAL_STARTUP_SCRIPT=/etc/rc3.d/S50cloud-init-local
CLOUD_INIT_STARTUP_SCRIPT=/etc/rc3.d/S51cloud-init
CLOUD_CONFIG_STARTUP_SCRIPT=/etc/rc3.d/S52cloud-config
CLOUD_FINAL_STARTUP_SCRIPT=/etc/rc3.d/S53cloud-final
PATH_TO_IFCFG_FILES=/etc/sysconfig/network-scripts
rm -f \$PATH_TO_JOB_ID\$PATH_TO_UDEV_NET_RULES_FILES/70-persistent-net.rules*
echo \"GATEWAY=${IP_GATEWAY}\" >> \$PATH_TO_JOB_ID\$PATH_TO_GATEWAY_FILE
rm -f \$PATH_TO_JOB_ID\$CLOUD_INIT_LOCAL_STARTUP_SCRIPT
rm -f \$PATH_TO_JOB_ID\$CLOUD_INIT_STARTUP_SCRIPT
rm -f \$PATH_TO_JOB_ID\$CLOUD_CONFIG_STARTUP_SCRIPT
rm -f \$PATH_TO_JOB_ID\$CLOUD_FINAL_STARTUP_SCRIPT" > "${PRE_FAILOVER_SCRIPT_LOCATION}"
echo "sed '/^BOOTPROTO/d' \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1} > \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.new
{
echo 'NAME=${INTERFACE_1}'
echo 'IPADDR=${IP_1}'
echo 'NETMASK=${SUB_1}'
echo 'BOOTPROTO=static'
} >> \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.new
cp \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1} \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.ori
mv \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.new \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}
rm \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.ori" >> "${PRE_FAILOVER_SCRIPT_LOCATION}"
echo "sed '/^BOOTPROTO/d' \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2} > \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}.new
{
echo 'NAME=${INTERFACE_2}'
echo 'IPADDR=${IP_2}'
echo 'NETMASK=${SUB_2}'
echo 'BOOTPROTO=static'
} >> \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}.new
cp \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2} \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}.ori
mv \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}.new \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}
rm \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_2}.ori" >> "${PRE_FAILOVER_SCRIPT_LOCATION}"
The script works perfectly, problem is that now I'm having multiple VMs with 3 or 1 NIC instead of 2 and I was wondering if there was a way to make a for loop that does the same thing but for each Network card. As you can see now I'm generating 'manually' the ifcfg-eth for each NC based on the info collected before:
{
echo 'NAME=${INTERFACE_1}'
echo 'IPADDR=${IP_1}'
echo 'NETMASK=${SUB_1}'
echo 'BOOTPROTO=static'
} >> \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.new
cp \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1} \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.ori
mv \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.new \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}
rm \$PATH_TO_JOB_ID\$PATH_TO_IFCFG_FILES/ifcfg-${INTERFACE_1}.ori" >> "${PRE_FAILOVER_SCRIPT_LOCATION}"```
Now it's no longer convenient but I'm not sure if what I'm trying to do is achievable.

How can I send a mail in linux shell script, using mail, but also awk?

What I really want is, I have a file: example.txt
The file is structured this way: FirstName LastName UserID Grade
I have two options: If the Grade is greater than 5 I want a mail to the user via [UserID]:
Dear [FirstName] [LastName]!
On this subject, your grade is [Grade]!
The second option is: If the [Grade] is less than 5 I want a mail to the user via [UserID]:
Dear [FirstName] [LastName]!
On this subject, your grade was less than 5!
Using awk'{print $1}' etc.
Thanks in advance!
Try the following script file :
#!/bin/bash
your_grade_files="/path_to_file.txt"
while read p; do
FirstName=$(echo $p | awk -F' ' '{print $1}')
LastName=$(echo $p | awk -F' ' '{print $2}')
UserID=$(echo $p | awk -F' ' '{print $3}')
Grade=$(echo $p | awk -F' ' '{print $4}')
if [ "$Grade" -gt 5 ]
then
mail -s "Enter your subject here" $UserID <<< "Dear $FirstName $LastName! On this subject, your grade is [ $Grade ] "
else
mail -s "Enter your subject here" $UserID <<< "Dear $FirstName $LastName! On this subject, your grade was less than 5!"
fi
done < $your_grade_files
Based on your question , You ll need to read the contents of the file iteratively
As you parse the contents line by line you can apply the mail to be triggered , based on the Grade value
while read line; do
grade = $(echo $line | awk -F' ' '{print $4}')
userid = $(echo $line | awk -F' ' '{print $3}')
if [[ $grade -gt 5]] then
sendMail $userid $grade
done < file.txt
func sendMail(){
userid = $1
grade = $2
MESSAGE="[$] : Your Grade -- $2"
SUBJECT="SOME SUBJECT"
TOADDR="u#u.com"
FROM="DONOTREPLY"
echo $MESSAGE | mail -s "$SUBJECT" $TOADDR -f $FROM
}
You can further modify the code snippet based on your requirement

Linux script shows unnecessary files

I have written following script and it shows some unnecessary files when i'm running it. I just want to execute only the command and receive the alerts only.
the script as follows
df -h | nawk '/backup/ {print $5 " " $6}' | while read line;
do
usep=$(echo $line | nawk '{printf "%d", $1}' )
partition=$(echo $line | nawk '{print $2}')
if (( $usep >= 90)); then
echo "$partition ($usep%)" | mailx -s "172.27.68.101" 0234343456#alert.abc.lk;
echo "$partition ($usep%)" | mailx -s "172.27.68.101" amalw#abc.lk;
echo "$partition ($usep%)" | mailx -s "172.27.68.101" amalw#abc.lk;
fi
done
Follwing image shows the output problem
How can i add multiple recipient to this script without opening such directories?
To paste a multi-line bash code into terminal, add parenthesis around the lines otherwise each line gets run as a separate command as soon as it gets pasted:
(df -h | nawk '/backup/ {print $5 " " $6}' | while read line; do
usep=$(echo "$line" | nawk '{printf "%d", $1}')
partition=$(echo $line | nawk '{print $2}')
if(("$usep" >= 90)) ; then echo "$partition ($usep%)" | mailx -s "172.27.68.101" 0234343456#alert.abc.lk;
echo "$partition ($usep%)" | mailx -s "172.27.68.101" amalw#abc.lk;
echo "$partition ($usep%)" | mailx -s "172.27.68.101" amalw#abc.lk;
fi
done)
Firstly command df -h|grep backup|sed 's/\%//g'|awk '$5 >= 90 {print $5"% "$6}' for having FS(Partition) more than 90% usage.
the rest of command to alert trought mail. Then :
df -h|grep backup|sed 's/\%//g'|awk '$5 >= 90 {print $5"% "$6}'|while read USAGE PARTITION
do
echo "$PARTITION ($USAGE)"|mailx -s "172.27.68.101" "0234343456#alert.abc.lk,amalw#abc.lk"
done

How can i get all the users and their authorize_key in linux using shell script?

I am using the following script to get the key count. But its is not working, is any other method exists? or how should i fix the error?
#!/bin/bash
for i in `cat /etc/passwd` ; do\
echo $i |\
awk -F: { print `grep -o "ssh-rsa" <<< (cat /home/"$1"/ .ssh/authorized_keys ) | wc -l` }
done
If you just want to display the number of keys, you can do this:
for homedir in $(awk -F':' '{print $6}' /etc/passwd); do
[[ -f "${homedir}/.ssh/authorized_keys" ]] && cat "${homedir}/.ssh/authorized_keys"
done
To display the counts for each file:
for homedir in $(awk -F':' '{print $6}' /etc/passwd); do
[[ -f "${homedir}/.ssh/authorized_keys" ]] && wc -l "${homedir}/.ssh/authorized_keys"
done
To display the counts by username:
while IFS='' read -r line || [[ -n "$line" ]]; do
USERNAME="$(echo "$line" | awk -F: '{print $1}')"
HOMEDIR="$(echo "$line" | awk -F: '{print $6}')"
if [[ -f "${HOMEDIR}/.ssh/authorized_keys" ]]; then
COUNT="$(grep -c 'ssh-' "${HOMEDIR}/.ssh/authorized_keys")"
else
COUNT=0
fi
echo "${USERNAME} has ${COUNT} keys."
done < "/etc/passwd"

trim ';' and split by ":"

I need to read a file like
#sys_platform:top_agent_id:channel
# 2 : 999 : 999
2:10086:10086;
2:999:999;
how to read sys_platform and top_agent_id, channel line by line
I write a shell , but not correctly
#!/bin/sh
sys_platform=""
top_agent_id=
channel=""
while read p; do
echo "line=$p"
echo $p | awk -F ':' '{print $1 $2 $3}' | read sys_platform top_agent_id channel
echo "sys_platform:${sys_platform}"
echo "top_agent_id:${top_agent_id}"
done < ./channellist.txt
result as :
line=#sys_platform:top_agent_id:channel
sys_platform:
top_agent_id:
line=# 2 : 999 : 999
sys_platform:
top_agent_id:
line=2:10086:10086;
sys_platform:
top_agent_id:
line=2:999:999;
sys_platform:
top_agent_id:
awk is your friend:
while read p; do
sys_platform=`echo $p | awk -F ':' '{print $1}'`
top_agent_id=`echo $p | awk -F ':' '{print $2}'`
channel=`echo $p | awk -F ':' '{print $3}' | tr -d ';'`
done < $filename
Nevertheless, you can do it directly with bash set builtin:
while read p; do
OFS=$IFS
IFS=':'
set -f
splitted=( $p )
set +f
sys_platform="${splitted[0]}"
top_agent_id="${splitted[1]}"
channel="${splitted[2]}"
IFS=$OFS
done < $filename
Less readable but should be more efficient.

Resources