How can we make a TIMER with (RESET) functionality in bash - bash

I am very new to shell scripting, I have googled many things for this problem. But cannot find a perfect solution to it.
Problem is: It's a log monitoring code with "ERROR", Pattern
How can we make a TIMER in unix scripting. Support I have a timer of 5 minutes, and time keep on decreasing every 1 second. So I want to reset again the timer to 5 minute on certain condition (say $FREQUENCY of ERROR occurrence is greater then say for ex2).
#!/usr/bin/env bash
PATTERN='ERROR'
TIMER=300
FREQUENCY=2
while true;
do grep -i $PATTERN logfile > tmp_log
while [ $TIMER -gt 0 ]
do
sleep 1 &
printf " $TIMER \r" &
TIMER=$[$TIMER-1];
wait
done
if [[ $(wc -l <tmp_log) -ge $FREQUENCY ]]
then
TIMER=300
echo $TIMER
fi
sleep $TIMER
done

#!/bin/bash
PATTERN='ERROR'
TIMER=300
FREQUENCY=2
while true
do
while [ $TIMER -gt 0 ]
do
sleep 1
TIMER=$((TIMER - 1))
grep -i $PATTERN logfile > tmp_log
count=`wc -l tmp_log | awk '{ print $1 }'`
if [ $count -gt $FREQUENCY ]
then
TIMER=300
fi
done
break
done
This is good going for your case.

Related

How to print in the same line as a progress in bash script

I want to print the text in the following manner
Waiting for completion.
Waiting for completion..
Waiting for completion...
[Note :Not more than three dots]
The above should be in the same line and in a loop.
When the loop condition is false I want to get the following in the same line as well :
Waiting for completion... [OK]
How do I achieve this in bash script?
You should use carriage return. Search information in echo about \r.
for example maybe you want something like this:
#!/bin/bash
while [ 3 -gt 2 ];
do
echo -n -e 'Esperando.\r'
sleep 1
echo -n -e 'Esperando..\r'
sleep 1
echo -n -e 'Esperando...\r'
sleep 1
echo -n -e ' \r'
done
You need to sleep cause if you dont sleep you won't be able to watch the changing dots.
How about this:
#!/usr/bin/env bash
trap ctrl_c INT
ctrl_c()
{
flag=1
}
dots()
{
if [ "$1" -eq 1 ]
then
echo .
fi
if [ "$1" -eq 2 ]
then
echo ..
fi
if [ "$1" -eq 3 ]
then
echo ...
fi
}
flag=0
dots_count=1
while [ "$flag" -eq 0 ]
do
if [ "$dots_count" -eq 4 ]
then
dots_count=1
fi
printf "\r%sWaiting for completion%s" "$(tput el)" "$(dots "$dots_count")"
dots_count=$((dots_count + 1))
sleep 1
done
printf "\r%sWaiting for completion... [OK]\n" "$(tput el)"
It will continuously print Waiting for completion followed by up to
three dots in the same line. When Control-c is
pressed then "Waiting for completion... [OK]" will be printed.
Use echo's "-n" switch
next echo will print on the same line

Check if a process is running with shell script

I'm trying to make a script to see if the process chromium is running.
The script should check every 10 seconds if the process is running and it must end when it finds it 10 times.
Here is my code.
#!/bin/bash
count=0
while true; do
sleep 10s
isthere=`$(top) | grep -w chromium`
if [ $isthere -ne 0 ]; then
count=$((count+1))
fi
if [ $count -eq 10 ]; then
echo "You found the process 10 times"
exit 50
fi
done
I'm having no output whatsoever. I don't know if I'm using the command top properly.
Yep, your usage of top command is incorrect. You try to invoke it from the shell script and it hangs as a result.
You should use top command with some specific options. I suggest you use it with -b option which corresponds to the "batch" mode and -n options which is for the number of iterations top produces its output. For more information check man top.
Also the test for isthere variable should be amended (we check it for non-emptyness).
The resulting script which works is something like this:
#!/bin/bash
count=0
while true; do
sleep 10s
isthere=`top -b -n 1 | grep -w chromium`
if [ -n $isthere ]; then
count=$((count+1))
fi
if [ $count -eq 10 ]; then
echo "You found the process 10 times"
exit 50
fi
done
Please use pgrep.
$ if pgrep ksh >/dev/null; then echo "ksh is running"; fi
ksh is running
In a loop:
i=0
while (( i < 10 )); do
if pgrep ksh >/dev/null; then
(( ++i ))
fi
sleep 10
done
Substitute ksh with the tool of your choice.

Check if output file is generated and populated with expected logs - BASH

A process (in background) should create a file (e.g. result.txt) and populate it with 5 log lines.
I need to check: 1) if the file exists and 2) checks if all the logs (5 lines) are stored
If these conditions are not satisfy within xxx seconds, the process failed and print "FAILED" in terminal, otherwise print "SUCCEED".
I think I need to use a while loop, but I don't know how to implement these conditions
N.B: the lines are appended into the file (asynchronously) and I don't have to check the compliance of logs, just to check if all are stored
This one checks the log and waits 2 seconds before failing:
#!/bin/sh
log_success() {
[[ $(tail -n "$2" "$1" 2> /dev/null | wc -l) -eq "$2" ]]
}
log_success 'file.log' 5 || sleep 2
if log_success 'file.log' 5; then
echo "success"
else
echo "fail"
fi
Well here's my draft for that:
FILE=/path/to/something
for (( ;; )); do
if [[ -e $FILE ]] && WC=$(wc -l < "$FILE") && [[ WC -ge 5 ]]; then
: # Valid.
fi
done
Or
FILE=/path/to/something
for (( ;; )); do
if [[ ! -e $FILE ]]; then
: # File doesn't exist. Do something.
elif WC=$(wc -l < "$FILE") && [[ WC -ge 5 ]]; then
: # Valid.
else
: # File doesn't contain 5 or more lines or is unreadable. Invalid.
fi
done
This one could still have problems with race conditions though.

bash: running cURLs in parallel slower than one after another

We have to cache quite a big database of data after each upload, so we created a bash script that should handle it for us. The script should start 4 paralel curls to the site and once they're done, start the next one from the URL list we store in the file.
In theory everything works ok, and the concept works if we run the run 4 processes from our local machines to the target site.
If i set the MAX_NPROC=1 the curl takes as long as it would if the browser hits the URL
i.e. 20s
If I set the MAX_NPROC=2 the time request took, triples.
Am I missing something? Is that an apache setting that is slowing us down? or is this a secret cURL setting that I'm missing?
Any help will be appreciated. Please find the bash script below
#!/bin/bash
if [[ -z $2 ]]; then
MAX_NPROC=4 # default
else
MAX_NPROC=$2
fi
if [[ -z $1 ]]; then
echo "File with URLs is missing"
exit
fi;
NUM=0
QUEUE=""
DATA=""
URL=""
declare -a URL_ARRAY
declare -a TIME_ARRAY
ERROR_LOG=""
function queue {
QUEUE="$QUEUE $1"
NUM=$(($NUM+1))
}
function regeneratequeue {
OLDREQUEUE=$QUEUE
echo "OLDREQUEUE:$OLDREQUEUE"
QUEUE=""
NUM=0
for PID in $OLDREQUEUE
do
process_count=`ps ax | awk '{print $1 }' | grep -c "^${PID}$"`
if [ $process_count -eq 1 ] ; then
QUEUE="$QUEUE $PID"
NUM=$(($NUM+1))
fi
done
}
function checkqueue {
OLDCHQUEUE=$QUEUE
for PID in $OLDCHQUEUE
do
process_count=`ps ax | awk '{print $1 }' | grep -c "^${PID}$"`
if [ $process_count -eq 0 ] ; then
wait $PID
my_status=$?
if [[ $my_status -ne 0 ]]
then
echo "`date` $my_status ${URL_ARRAY[$PID]}" >> $ERROR_LOG
fi
current_time=`date +%s`
old_time=${TIME_ARRAY[$PID]}
time_difference=$(expr $current_time - $old_time)
echo "`date` ${URL_ARRAY[$PID]} END ($time_difference seconds)" >> $REVERSE_LOG
#unset TIME_ARRAY[$PID]
#unset URL_ARRAY[$PID]
regeneratequeue # at least one PID has finished
break
fi
done
}
REVERSE_LOG="$1.rvrs"
ERROR_LOG="$1.error"
echo "Cache STARTED at `date`" > $REVERSE_LOG
echo "" > ERROR_LOG
while read line; do
# create the command to be run
DATA="username=user#server.com&password=password"
URL=$line
CMD=$(curl --data "${DATA}" -s -o /dev/null --url "${URL}")
echo "Command: ${CMD}"
# Run the command
$CMD &
# Get PID for process
PID=$!
queue $PID;
URL_ARRAY[$PID]=$URL;
TIME_ARRAY[$PID]=`date +%s`
while [ $NUM -ge $MAX_NPROC ]; do
checkqueue
sleep 0.4
done
done < $1
echo "Cache FINISHED at `date`" >> $REVERSE_LOG
exit
The network is almost always the bottleneck. Spawning more connections usually makes it slower.
You can try to see if parallel'izing it will do you any good by spawning several
time curl ...... &

KSH: Spread commands equally over time

I'm working on a ksh performance script. It takes the following options:
- i (interval time)
- p (messages per interval)
- t (total messages)
So for example: "script -i 1 -p 2 -t 10" means 2 messages per second to a maximum of 10.
This is working, but the script does not yet equally spread the messages over the given interval time. In this example the script should execute the second command after 0.5 seconds, not before.
Is it possible to do this easily?
In short, this is what I have so far:
typeset -i i=0
typeset -i n=0
while [ $i -lt $TOTAAL ]; do
while [ $n -lt $PERINT ]; do
# execute this command
n=$((n+1))
done
i=`expr $i + $PERINT`
# Reset n
n=0
# Wait interval time
sleep $INTERVAL
done
-i: $INTERVAL is an integer (0, 1, 2...) and not calculated in any way. I have done input checks to prevent input the script does not expect.
-t: $TOTAAL
-p: $PERINT
According to serverfault question 340838 Aix 5.3 ships with a separate ksh93 binary in /usr/bin/ksh93.
This will have subsecond sleep and floating point arithmetic. Watch out for fence-post errors, when calculating the interval.
Thanks to Henk Langeveld, I found out ksh93 was pre-installed. This is the new script. It seems to work fine.
typeset -i i=0
typeset -i n=0
while [ $i -lt $TOTAAL ]; do
while [ $n -lt $PERINT ]; do
# execute this command
sleep $VERDELING
n=$((n+1))
done
i=$((i+PERINT))
# Reset n
n=0
done
These are some of the checks I use. I translated the error-messages.
if [[ $PERINT -gt $TOTAAL ]]; then
echo "[[31mFOUT[0m] Messages per interval cannot be greater then total amount"; exit
fi
VERGELIJK=`echo "scale=1; $TOTAAL / $PERINT" | bc`
if [[ $VERGELIJK = *.[1-9]* ]]; then
echo "[[31mFOUT[0m] Messages per interval has to be a multiple of the total amount"; exit
fi
VERDELING=`echo "scale=2; $INTERVAL / $PERINT" | bc`

Resources