Trigger a shell Script on log file change - linux

I'm looking to trigger a command on xrdp session start and end, if /var/log/xrdp.log file get update with session started in last 10 minutes, I would like to trigger a shell script.
Example: Session Login Trigger.
[root#CentOS73-RDPDemo sp]# cat trigger-login.sh
#!/bin/bash
if [ $(( $(date +%s) - $(date +%s -r /var/log/xrdp.log) )) -le 180 ]; then
tail -n 4 /var/log/xrdp.log | grep -i "socket: 11"
sh /usr/src/sp/sql-login.sh
fi
Example: Session Logout Trigger
[root#CentOS73-RDPDemo sp]# cat trigger-logout.sh
#!/bin/bash
if [ $(( $(date +%s) - $(date +%s -r /var/log/xrdp.log) )) -le 180 ]; then
tail -n 4 /var/log/xrdp.log | grep -i "socket: 12"
sh /usr/src/sp/sql-logout.sh
fi

Write a script (say main.sh) which checks if there is any update in file (var/log/xrdp.log). If there is any update in file, call your desired scripts (trigger-login.sh and trigger-logout.sh).
You can do it using stat or md5sum
Example for reference (main.sh).
#!/bin/bash
touch /tmp/checkMD5
nchksum=`md5sum a.out | awk -F " " '{print $1}'`
ochksum=`cat /tmp/checkMD5`
if [ "$nchksum" == "$ochksum" ]; then
echo "both are same"
else
sh trigger-login.sh
sh trigger-logout.sh
fi
echo $nchksum >/tmp/checkMD5
schedule a crontab job which will run the main.sh script in every 10 minutes.

Related

.sh script linux math with numbers 00-59 [duplicate]

This question already has answers here:
Value too great for base (error token is "09")
(7 answers)
Value too great for base (error token is "08") [duplicate]
(1 answer)
Closed 5 months ago.
I have a script that looks at the current time, does some tasks and notifies me 1 minute before the timer ends. For some reason there is a problem and the script does not pass the condition "IF"
I read that it seems like bash interprets numbers not as a decimal number. I tried to solve the problem by removing the first zero from the string. Bash will understand this as a decimal number and perform a subtraction operation.
For example. Turn off the computer after 10 minutes. Now is 01:00:00. Shutdown at 01:10:00
The script makes a timecode file with name "T01H10M.shutdown" and takes all the necessary numbers of hour and minute from it.
When the time comes to 01:09:00, the script notifies me about the imminent completion of the work.
#Search shutdown time from file name
SearchFilenameDateWhenPCgotoShutdown="$(find /root/ -name '*.shutdown')"
SearchTimeHour=$(echo $SearchFilenameDateWhenPCgotoShutdown | cut -f2 -d "T"| cut -f1 -d "H")
SearchTimeMinute=$(echo $SearchFilenameDateWhenPCgotoShutdown | cut -f2 -d "H" | cut -f1 -d "M")
#Calculation of the penultimate minute and сorrection of the subtraction error.
SearchTimeMinuteMinus1=$(($SearchTimeMinute - 1 ))
if [ $SearchTimeMinuteMinus1 -eq -2 ]; then
SearchTimeMinuteMinus1=58;
fi
if [ $SearchTimeMinuteMinus1 -eq -1 ]; then
SearchTimeMinuteMinus1=59
fi
#Determining the current hour and minute
RealTimeHour=$(date "+%H")
RealTimeMinute=$(date "+%M")
if [ $RealTimeMinute = 00 ];
then
RealTimeMinute=0;
else
RealTimeMinute=`echo $RealTimeMinute |sed 's/^0*//'`
fi
#The condition matches the current hour
if [ $SearchTimeHour = $RealTimeHour ]; then
if [ $SearchTimeMinuteMinus1 = $RealTimeMinute ]; then
curl -s "https://api.telegram.org/bla bla bla bla &> /dev/null
fi
And here there is an error that when the current time is in minutes from 00-07 minutes, the condition IF = 00 then = 0 else remove "0" work fine and corrects the number to decimal with a condition. Output 1, 2, 3...7 And when the minute is already 08, the script stops at the stage of checking minutes.
if [ $SearchTimeMinuteMinus1 = $RealTimeMinute ]; then
And I don't understand why!
I tried to do it in a separate script.
B=08
if [ $B = 00 ];
B=0;
else
B=`echo $B |sed 's/^0*//'`
fi
echo $B
He works. Output 8. Why I can't do it in the main script, I don't understand.
Screenshot with each 2 min script run
Help please.
--------------------UPD 4.10.22--------------------
OK! Thank you all for your advice. I fixed the code and it works. But! Another problem :D When the time comes at 59 minutes. An error occurs in stage.
if [ $SearchTimeHour = $RealTimeHour ]; then
Problem
This is very strange! After all, all variables are defined correctly. Any ideas?
Full code:
#!/bin/bash
if ping -c 2 100.100.100.100 | grep "ttl"; then
if ping -c 2 192.168.10.1 | grep "ttl"; then
if ping -c 2 192.168.88.102 | grep "ttl"; then
#OMV name
NameOMV="Standart OMV"
#The option determines how many minutes to turn off the system
ShutDownParameterMinutes=2
#Defining the startmark file in the script
startmark=/root/startmark
#Checking the existence of the startmark file
if [ -f $startmark ]
then
#Recording when to switch off to a variable
SearchFilenameDateWhenPCgotoShutdown="$(find /root/ -name '*.shutdown')"
#Determination of the hour and minute of shutdown
SearchTimeHour=$(echo "$SearchFilenameDateWhenPCgotoShutdown" | cut -f2 -d "T"| cut -f1 -d "H")
SearchTimeMinute=$(echo "$SearchFilenameDateWhenPCgotoShutdown" | cut -f2 -d "H" | cut -f1 -d "M")
#Determination of the hour and minute of shutdown minus 1 minute for notification in telegrams
#Correction of the subtraction error of 2 minutes - 2 minutes becomes 58 minutes, and -1 = 59 minutes
SearchTimeMinuteMinus1=$((SearchTimeMinute - 1 ))
if [ "$SearchTimeMinuteMinus1" -eq -2 ]; then
SearchTimeMinuteMinus1=58
fi
if [ "$SearchTimeMinuteMinus1" -eq -1 ]; then
SearchTimeMinuteMinus1=59
fi
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 SearchTimeMinuteMinus1=${SearchTimeMinuteMinus1}" &> /dev/null
#Determining the current hour and minute
RealTimeHour=$(date "+%H")
RealTimeMinute=$(date "+%M")
RealTimeMinute=$((10#$RealTimeMinute))
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 RealTimeHour=${RealTimeHour}" &> /dev/null
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 RealTimeMinute=${RealTimeMinute}" &> /dev/null
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 TICK $(date "+%d.%m.%Y - %H:%M:%S")" &> /dev/null
#The condition matches the current hour
if [ "$SearchTimeHour" -eq "$RealTimeHour" ]; then
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 Hour OK" &> /dev/null
if [ "$SearchTimeMinuteMinus1" -eq "$RealTimeMinute" ]; then
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 Minute OK" &> /dev/null
rm "$SearchFilenameDateWhenPCgotoShutdown"
rm startmark
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 $NameOMV is less 1 minutes left before shutdown" &> /dev/null
fi
fi
else
#Creating a startmark
touch startmark
#Notification in telegram about the start of the shutdown procedure
echo "OrangePi is creating startmark to offline: $(date "+%d.%m.%Y - %H:%M:%S")" >> shutdownlog.txt
#We determine the time when to turn off
DateWhenPCgotoShutdown=$(date +"T""%H""H""%M""M" --date="$ShutDownParameterMinutes minute")
TimeStampStartName="${DateWhenPCgotoShutdown}.shutdown"
touch "$TimeStampStartName"
chmod +x "$TimeStampStartName"
#Notification in telegram when to turn off the computer
TelegramMessage="OrangePi $NameOMV is creating startmark to offline: $(date "+%d.%m.%Y - %H:%M:%S" --date="$ShutDownParameterMinutes minute")"
echo "${TelegramMessage}" >> shutdownlog.txt
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 $TelegramMessage" &> /dev/null
#/sbin/shutdown -h +$ShutDownParameterMinutes
echo "SHUTDOWN"
fi
fi
fi
fi
With respect.

Bash script: read 30000 records from file and run multiple process in parallel

txt with more than 30000 records.
All records are one for line and is an IP like this:
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
I read each row in a bash script, and I need to run a curl like this:
while IFS= read -r line || [[ -n "$line" ]]; do
#check_site "$line"
resp=$(curl -i -m1 http://$line 2>&1)
echo "$resp" | grep -Eo "$ok" > /dev/null
if [ $? -ne 0 ]; then
#echo -e "failed: $line" >> "${logfile}"
echo -e "Command: curl -i -m1 http://$line 2>&1" >> "${outfile}"
echo -e "failed: $line:\n\n \"$resp\"\n\n" >> "${outfile}"
echo "$line" >> "${faillog}"
fi
done < "${FILE}"
Is there a method to run multiple lines simultaneously in my file to reduce the execution time?
I solved for the multiprocess in this way:
#export variable to be used into function
export outlog="/tmp/out.log"
export faillog="/tmp/fail.log"
export ok="(curl: \(7\) Failed to connect to)" # acceptable responses
# create function:
check_site() {
ip=$1
resp=$(curl -i -m1 http://$ip 2>&1)
echo "$resp" | grep -Eo "$ok" > /dev/null
if [ $? -ne 0 ]; then
echo -e "Command: curl -i -m1 http://$ip 2>&1" >> "${outlog}"
echo -e "Block failed: $ip:\n\n \"$resp\"\n\n" >> "${outlog}"
echo "$ip" >> "${faillog}"
fi
}
# call the function:
export -f check_site
parallel -j 252 -a "${FILE}" check_site
Xargs will do the trick. Wikipedia
This article describe approach to resolve parallel execution, it may help you:
Parallel execution in Bash
Example from the article:
#!/bin/bash
RANDOM=10
JOBS_COUNTER=0
MAX_CHILDREN=10
MY_PID=$$
for i in {1..100}
do
echo Cycle counter: $i
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
while [ $JOBS_COUNTER -ge $MAX_CHILDREN ]
do
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
echo Jobs counter: $JOBS_COUNTER
sleep 1
done
sleep $(($RANDOM % 30)) &
done
echo Finishing children ...
# wait for children here
while [ $JOBS_COUNTER -gt 1 ]
do
JOBS_COUNTER=$((`ps ax -Ao ppid | grep $MY_PID | wc -l`))
echo Jobs counter: $JOBS_COUNTER
sleep 1
done
echo Done

Exit script if a file doesn't exist

I try to calculate time differences between two log, but when there is no log in logfile, unix takes own birthdate 1970. My script is below. I want to exit from script if there is no log in logfile.
#!/bin/bash
a=`tail -n 1 /var/log/nginx/error.log | awk -F" " '{print $1" "$2}' | cut -c12-20`
f=`date '+%Y-%m-%d %H:%M:%S' | cut -c12-19`
VAR1=$(date -u --date="$a sec UTC" +%s)
VAR2=$(date -u --date="$f sec UTC" +%s)
DIFF2=$(( $VAR2 - $VAR1 ))
if [ $DIFF2 -lt 59 ]; then
echo "ok"
else
echo "nok"
fi
I guess that with if there is no log in logfile, you mean that the logfile either does not exist or is empty. You can do this in bash with
logfile=/var/log/nginx/error.log
[[ -f $logfile && -s $logfile ]] || exit 1
-f tests that it is a plain file, and -s tests that it is not empty.
You can check fr the existence of a file using:
if [ ! -f '/var/log/ngnix/error.log' ]
then
exit
fi
Just check if file doesn't exist or is empty and exit code
LOG_FILE="/var/log/nginx/error.log"
[ ! -s $LOG_FILE -o ! -f $LOG_FILE ] && exit $?

bash script run to send process to background

Hi Im making a script to do some rsync process, for the rsync process, Sys admin has created the script, when it run it is asking select options, so i want to create a script to pass that argument from script and run it from cron.
list of directories to rsync take from file.
filelist=$(cat filelist.txt)
for i in filelist;do
echo -e "3\nY" | ./rsync.sh $i
#This will create a rsync log file
so i check the some value of log file and if it is empty i moving to the second file. if the file is not empty, i have to start rsync process as below that will take more that 2 hours.
if [ a != 0 ];then
echo -e "3\nN" | ./rsync.sh $i
above rsync process need to send to the background and take next file to loop. i check with the screen command, but screen is not working with server. also i need to get the duration that take to run process and passing to the log, when i use the time command i am unable to pass the echo variable. Also need to send this to background and take next file. appreciate any suggestions to success this task.
Question
1. How to send argument with Time command
echo -e "3\nY" | time ./rsync.sh $i
above one not working
how to send this to background and take next file to rsync while running previous rsync process.
Full Code
#!/bin/bash
filelist=$(cat filelist.txt)
Lpath=/opt/sas/sas_control/scripts/Logs/rsync_logs
date=$(date +"%m-%d-%Y")
timelog="time_result/rsync_time.log-$date"
for i in $filelist;do
#echo $i
b_i=$(basename $i)
echo $b_i
echo -e "3\nY" | ./rsync.sh $i
f=$(cat $Lpath/$(ls -tr $Lpath| grep rsync-dry-run-$b_i | tail -1) | grep 'transferred:' | cut -d':' -f2)
echo $f
if [ $f != 0 ]; then
#date=$(date +"%D : %r")
start_time=`date +%s`
echo "$b_i-start:$start_time" >> $timelog
#time ./rsync.sh $i < echo -e "3\nY" 2> "./time_result/$b_i-$date" &
time { echo -e "3\nY" | ./rsync.sh $i; } 2> "./time_result/$b_i-$date"
end_time=`date +%s`
s_time=$(cat $timelog|grep "$b_i-start" |cut -d ':' -f2)
duration=$(($end_time-$s_time))
echo "$b_i duration:$duration" >> $timelog
fi
done
Your question is not very clear, but I'll try:
(1) If I understand you correctly, you want to time the rsync.
My first attempt would be to use echo xxxx | time rsycnc. On my bash, this was however broken (or not supposed to work?). I'm normally using Zsh instead of bash, and on zsht, this indeed runs fine.
If it is important for you to use bash, an alternative (since the time for the echo can likely be neglected) would be to time the whole pipe, i.e. time (echo xxxx | time rsync), or even simpler time rsync <(echo xxxx)
(2) To send a process to the background, add an & to the line. However, the time command produces of course output (that's it purpose), and you don't want to receive output from a program in background. The solution is to redirect the output:
(time rsync <(echo xxxx) >output.txt 2>error.txt) &
If you want to time something, you can use:
time sleep 3
If you want to time two things, you can do a compound statement like this (note semicolon after second sleep):
time { sleep 3; sleep 4; }
So, you can do this to time your echo (which will take no time at all) and your rsync:
time { echo "something" | rsync something ; }
If you want to do that in the background:
time { echo "something" | rsync something ; } &
Full Code
#!/bin/bash
filelist=$(cat filelist.txt)
Lpath=/opt/sas/sas_control/scripts/Logs/rsync_logs
date=$(date +"%m-%d-%Y")
timelog="time_result/rsync_time.log-$date"
for i in $filelist;do
#echo $i
b_i=$(basename $i)
echo $b_i
echo -e "3\nY" | ./rsync.sh $i
f=$(cat $Lpath/$(ls -tr $Lpath| grep rsync-dry-run-$b_i | tail -1) | grep 'transferred:' | cut -d':' -f2)
echo $f
if [ $f != 0 ]; then
#date=$(date +"%D : %r")
start_time=`date +%s`
echo "$b_i-start:$start_time" >> $timelog
#time ./rsync.sh $i < echo -e "3\nY" 2> "./time_result/$b_i-$date" &
time { echo -e "3\nY" | ./rsync.sh $i; } 2> "./time_result/$b_i-$date"
end_time=`date +%s`
s_time=$(cat $timelog|grep "$b_i-start" |cut -d ':' -f2)
duration=$(($end_time-$s_time))
echo "$b_i duration:$duration" >> $timelog
fi
done

If date string is + or - 5 minutes then

I am new to bash scripts and trying to work an if statement out.
I want to do a check to see if the date stamp of a file is + or - 5 minutes from the time now. I have so far:
#!/bin/bash
MODDATE=$(stat -c '%y' test.txt)
echo moddate= $MODDATE
MODDATE=$(echo $MODDATE |head --bytes=+16)
echo now = $MODDATE
currentdate2=$(date -d "+5 minutes" '+%Y-%m-%d %H:%M')
currentdate3=$(date -d "-5 minutes" '+%Y-%m-%d %H:%M')
echo currentdate2 = $currentdate2
echo currentdate3 = $currentdate3
So this gives me the datestamp of the file (MODDATE) and the date now + or - 5 minutes.
How can i do an IF statement to say "if $MODDATE is between $currentdate2 (+5 minutes from now) and $currentdate3 (-5 minutes from now)" then echo [1] > output.txt ELSE echo [0] > output.txt .
Thank you for all of your help in advance
I recommend you to use date %s to have the date in seconds since 1/1/1970 and make date comparison much easier.
currentdate2=$(date -d "+5 minutes" '+%s')
currentdate3=$(date -d "-5 minutes" '+%s')
Hence,
if [ $moddate -ge $currentdate2 ] && [ $moddate -le $currentdate3 ]; then
....
fi
should make it.
Or even shorter:
[ $moddate -ge $currentdate2 ] && [ $moddate -le $currentdate3 ] && echo "in interval!"
How about you don't try to parse the output of stat and directly take its output in seconds since Epoch with %Y? It would then be easier to use Bash's arithmetic.
Your script would look like this (with proper quoting, modern Bash constructs and lowercase variable names):
#!/bin/bash
moddate=$(stat -c '%Y' test.txt)
echo "moddate=$moddate"
now=$(date +%s)
if ((moddate<=now+5*60)) && ((moddate>=now-5*60)); then
echo "[1]" > output.txt
else
echo "[0]" > output.txt
fi

Resources