2

I have a bash that has 2 while loops, the first is an infinite loops that tracks some events, and the second reads a log file and does something when a specific line shows up:

#!/bin/bash

while [ 1 ]; do
    ...
done &

date=`date +%Y%m%d`
file="logs/$date.log"

tail -f $file | grep --line-buffered "ALERT" | while read line
do
    ...
done

This works great, my only issue is that each day after 00:00 the log rotates to a new day (this is sadly out of my control), how can I rerun the second while loop at 00:01 ? (log rotation is at first write but I don't mind losing a minute)

Using cron to kill everything and restart is not great because it also kills my first loop, so I was thinking there must be an intelligent way to do this from inside the script.

6
  • 1
    Could you put the first loop into a separate script, and use cron to kill the second one anyway? Not saying it's the best solution, but it might be a solution. Commented Feb 21, 2018 at 10:08
  • What do you mean by return the second loop? Do you want to break it means stop it at 00.01? Are you going to restart it again? If so when? Commented Feb 21, 2018 at 10:09
  • @Thomas The 2 while loops are sort of related so it would be great to have them in the same script if posible. Commented Feb 21, 2018 at 10:12
  • @Abhijit Break at 00:01 and restart it at the same time with a new filename (new date of the log, ie 20180203.log instead of 20180202.log) Commented Feb 21, 2018 at 10:14
  • @Debrian, what are the commands you are using inside that while loop? Commented Feb 21, 2018 at 10:17

2 Answers 2

1

You can run the second loop inside a third loop. In each iteration, the that third loop restarts the second loop. Use sleep to start the next iteration at 00:01.

#!/bin/bash

secondLoop() {
    date=$(date +%Y%m%d)
    file="logs/$date.log"

    tail -f $file | grep --line-buffered "ALERT" | while read line; do
        ...
    done
}

while true; do
    ...
done &

while true; do
    secondLoop &
    pidSecondLoop=$!
    sleep $(($(date -d 'tomorrow 00:01' +%s) - $(date +%s)))
    kill $pidSecondLoop
done
Sign up to request clarification or add additional context in comments.

4 Comments

Looks great, will give it a try and get back.
@Debrian, just consider it as above example is looking good but as it kill the function no work should stop midway.
As a hacky alternative to killing the loop, write a code word like end of log to the last log. The second loop should terminate when the code word is read, for instance with [ "$line" == "end of log" ] && break.
I can't touch the log, but this works exactly as needed, tested a few hours and it goes great. @Debrian, it should not be an issue as the log is very low volume and it repeats the error in the worse case that it misses one.
0

You can do it by introducing a function in your script. Add one function and move your while loop including codes into it and break the loop every day when time is greater than 00.01. Call the function from a infinite while loop as you are doing in your code. Once your break the while loop function will return and from infinite while loop you will call the function again with a new log file name.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.