Scenario:
We have a bash script that performs various functions related to Freeradius, including expiration checkup & various groups updates functions.
Problem:
We have schedules this script to run daily at 1700 hours, What will happen if server was powered off at 1700 hours? Script will missed its schedule resulting in expired users account will not be disabled for that day and incorrect display of users status in front gui. Alternatively we can schedule it to run hourly but it will increase the server load because of repeated task , which is supposed to be executed only once per day
Requirements:
We need to make some checks and balances so that if script must have some intelligent IF ELSE criteria in order to check following steps …
- Script is scheduled to run hourly, so that if it misses the 1700 hour it will be relaunched next hour,
- If time is 1700 hours or above then execute the script,
- If the script executes successfully , then save this result, and on next run (within current date) it should detect last run status and dont repeat the code to avid recurrence,
- If the last run was not executed for any reason, & the time is 1700 or above then execute the script and save its run status in file,
- Once the data changes, it should re-run the script only if the time is 1700 or above.
Solution:
the SCRIPT ! Sample Purpose only
#!/bin/bash # Bash Script to make sure script runs at specific time, and should not run again for the same date # record date in local file, to avoic repeating running the code in todays date, once the date is changed, # then re-run the code and match time again and so on # Syed Jahanzaib / 26-Jun-2018 # set -x # Setting variables DATE=$(date +%d-%m-%Y) FULL_DATE=`date` FILE=/temp/1.txt touch $FILE CURR_HOUR=$(date +%H) # Set time for script execution SCR_SCHEDULED_TIME="11" H=$(date +'%-H') CHK_GREP=`grep -c $DATE $FILE` echo "Current Date time is $FULL_DATE" # If script is executed successfully then dont re-run and exit now if grep -q $DATE $FILE >/dev/null 2>&1 then echo "It seems the script was executed successfully today $DATE, It will run on next date change.... Exiting now." exit 1 fi # Check if time is matched that is greater or equals to $SCR_SCHEDULED_TIME and also check if script hae ran successfully or not previously echo " Stage-1: Checking if current time is equals or greater then '$SCR_SCHEDULED_TIME hours' ..." if [ "$CURR_HOUR" -ge "$SCR_SCHEDULED_TIME" ] && [ "$CHK_GREP" == "0" ]; then echo " Stage-2: Time matched that is equals or greater then $SCR_SCHEDULED_TIME" # If all matches, then run the code ! and add time stamp in file to avoid repeatingo/re-running the following script code on next RUN echo "Finally: All conditions time + this day first execution matched, Now running the script code ...." date +%d-%m-%Y >> $FILE exit 1 fi # If time have not come like its before the $SCR_SCHEDULED_TIME, then give error and exit now echo " Warning ! Scheudled time is equals or greater then $SCR_SCHEDULED_TIME hours : Current hour is $CURR_HOUR Time have not came yet ! wait for your turn ..."
This way I was able to achieve the task I was thiking of.
# Actual Script which performs various functions with time checkups etc
Just for personnel reference …
#!/usr/bin/env bash ####!/bin/sh #set -x #trap "set +x; set -x" DEBUG # BASH base script to discopnnect users whose expiry is today & update there GROUPS as well and update log table. # the simple logic can be applied for about any other task as well. I tried to make it as simple as it can be # also check if the scrpit ran successfully then dont re-run today, # By Syed Jahanzaib # CREATED on : 16th July, 2015 # Modified on 25h June 2018 # Local Variables # Mysql credentials SQLID="root" SQLPASS="ROOTPASS" export MYSQL_PWD=$SQLPASS CMD="mysql -u$SQLID --skip-column-names -s -e" DB="radius" #Table which contain main users information TBL="users" #Rad user group in which we will update user profile like from 1mb to expired or likewise GROUP="radusergroup" NEXTSRV="expired" TBL_LOG="log" # Date Time Variables DATE=$(date +%d-%m-%Y) FULL_DATE=`date` CURR_HOUR=$(date +%H) TODAY=$(date +"%Y-%m-%d") WEEK=`date -d "-1000 days" '+%Y-%m-%d'` BEGIN="1970-01-01" H=$(date +'%-H') ################################ ## Set time for script execution ## IMPORTANT, donot use 0 in it SCR_SCHEDULED_TIME="12" ################################ #Network Related hostname=`hostname` IP=`ip route get 8.8.8.8 | awk '{print $NF; exit}'` # Gmail Data GMAILID="MYGMAIL@gmail.com" GMAILPASS="MYGMAILPASS" SMTP="64.233.184.108:587" ADMINMAIL1="aacableAThotmail.com" COMPANY="ZAIB" MAILSUB="$COMPANY INFO -$HOSTNAME-$IP- List of account expired on $TODAY" ################################################## ################################################## # Temp folder and files setup for various actions ################################################## ################################################## TEMP="temp" # Temp holders to store users list ALLEXPLIST=/$TEMP/all_time_expired_users_list.txt TODEXPLIST=/$TEMP/only_today_expired_users_list.txt FILE=/$TEMP/check_user_expiration_exec.txt # Checking if /temp folder is previously present or not , if not create one ... { if [ ! -d "/$TEMP" ]; then echo mkdir /$TEMP fi } # remove and recreate users list to avoid any Duplication or issue { if [ -f $ALLEXPLIST ]; then rm $ALLEXPLIST touch $ALLEXPLIST fi } { if [ -f $TODEXPLIST ]; then rm $TODEXPLIST touch $TODEXPLIST fi } # File Holder to store last execution date { if [ ! -f $FILE ]; then touch $FILE fi } ############################ ############################ ###### START thE script cOdE ############################ ############################ CHK_GREP=`grep -c $DATE $FILE` echo "Current Date time is $FULL_DATE " # If script is executed successfully in current date, then dont re-run and exit now echo "Stage-1: Checking if the script have already ran successfully for today, by getting current date from the $FILE" if grep -q $DATE $FILE >/dev/null 2>&1 then echo " Result: It seems the script was executed successfully today $DATE, It will run on next date change. Exiting now ..." exit 1 fi # Check if time is matched that is greater or equals to $SCR_SCHEDULED_TIME and also check if script hae ran successfully or not previously by getting date from $FILE echo " Stage-2: Checking if current hour is equals or greater then '$SCR_SCHEDULED_TIME hours' & previous run is not done yet ..." if [ "$CURR_HOUR" -ge "$SCR_SCHEDULED_TIME" ] && [ "$CHK_GREP" == "0" ]; then echo " Stage-2: Time matched that is equals or greater then $SCR_SCHEDULED_TIME" # If all matches, then run the code ! and add time stamp in file to avoid repeatingo/re-running the following script code on next RUN echo "Finally: All conditions time + this day first execution matched, Now running the script code ..." date +%d-%m-%Y >> $FILE # Pull users that are expiring from beginning till TODAY, to avoid missing any part $CMD "use $DB; select username from $TBL where expiration between '$BEGIN' AND '$TODAY';" |sort > $ALLEXPLIST # Pull user list that are expiring today only, for email purposes $CMD "use $DB; select username from $TBL where expiration ='$TODAY';" |sort > $TODEXPLIST # IF no user found , show error and exit - zaib CHK=`wc -m $ALLEXPLIST | awk {'print $1}'` if [ "$CHK" -eq 0 ] then echo "No user found expiring today, exiting ..." exit 1 fi # Apply formula num=0 cat $ALLEXPLIST |while read data do num=$[$num+1] USERNAME=`echo $data` # Update user status in RADgroup & users table so that he will rejected on next login IS_EXPIRED=`$CMD "use $DB; select is_expired from users where username ='$USERNAME';"` if [ "$IS_EXPIRED" = "N" ]; then echo "user_IS EXIPRED is NO *************************************************************************************************" $CMD "use $DB; update $GROUP set groupname='$NEXTSRV' where username='$USERNAME';" $CMD "use $DB; update $TBL set is_expired='Y' where username='$USERNAME';" $CMD "use $DB; update $TBL set is_days_expired='Y' where username='$USERNAME';" $CMD "use $DB; INSERT into $TBL_LOG (data, msg) VALUES ('$USERNAME', '$USERNAME - User reached Expiration, Group udpated.');" fi # CHECK ONLINE AND KICK # Pull account session id from radacct table, which will be used to COA OR user disconnection ACCTSESID=`$CMD "use $DB; select acctsessionid from radacct where username ='$USERNAME' AND acctstoptime is NULL;"` # If user is not Online , just give info that he is not online if [ -z "$ACCTSESID" ]; then $CMD "use $DB; INSERT into $TBL_LOG (data, msg) VALUES ('$USERNAME', '$USERNAME - User reached Expiration, Group udpated but its already offline');" echo "$USERNAME - User reached Expiration, Group udpated but its already offline." else # Kick user by getting his NAS ip, secret and other info and log # Mikrotik NAS IP and Radport and Shared Secret NAS_IP=`$CMD "use $DB; select nasipaddress from radacct where username ='$USERNAME' AND acctstoptime is NULL;"` NAS_SECRET=`$CMD "use $DB; select secret from nas where nasname ='$NAS_IP';"` NAS_COA_PORT=`$CMD "use $DB; select nas_coa_port from nas where nasname ='$NAS_IP';"` # Disconnect users now using RADCLIENT with username adn Account session ID taken from radacct table echo user-name=$USERNAME,Acct-Session-Id=$ACCTSESID | radclient -x $NAS_IP:$NAS_COA_PORT disconnect $NAS_SECRET # LOG into LOG TABLE in radius DB $CMD "use $DB; INSERT into $TBL_LOG (data, msg) VALUES ('$USERNAME', '$USERNAME - User reached Expiration, kicked & updated,.');" echo "$USERNAME - User reached Expiration, kicked & updated." fi done #TOT=`cat $TODEXPLIST | wc -l` #echo " #----------- #----------- #$COMAPNY _ List of TODAY $TODAY expired users, Total = $TOT" #cat $TODEXPLIST # Send Email to all admin - currently 4 users sendemail -t $GMAILID -u "$MAILSUB" -o tls=yes -s $SMTP -t $ADMINMAIL1 -xu $GMAILID -xp $GMAILPASS -f $GMAILID -o message-file=$TODEXPLIST -o message-content-type=text fi
Regard’s
Syed Jahanzaib