1

So, I need to make a modification to a start script to clean up the /tmp once the application is fully loaded. After some research, I found a command for my script that does this:

tail -f /home/user1/logs/application.log | awk '/Application is fully up and running/ { system("pm2 restart cleantmp"); exit 1; }'

echo "Startup complete"

Basically, it checks each newline of the script for the pattern 'Application is fully up and running', and when that occurs, uses pm2 to restart a cleanup process we have.

This seems work as far as cleaning up /tmp after the application starts. However, I'm running into an issue where the console will then just hang there, showing me the server output, and never exiting. It does not fail or through an error; it simply never reaches the echo statement, and waits for me to use CTRL+C.

Based on my research on this site,I've tried other versions of this using tail and sed:

tail -f /home/user1/logs/application.log | grep --line-buffered -q 'Application is fully up and running' | while read ; do pm2 restart cleantmp ; done
tail -f /home/user1/logs/application.log | sed "/Application is fully up and running/q"

In both cases, the script did not even get to cleanup. Further testing with "ps -aux | grep tail" shows that it is definitely tail -f that is preventing the script from completing. Has anyone had a similar use case to this? Any suggestion would be greatly appreciated.

2
  • Is the "up and running" line the last thing that gets written to the log, or is there more to come after it? After the awk/grep/whatever exits, tail only sees the pipe close when it next tries to write there. If that never happens, well, there's the hang.
    – ilkkachu
    Aug 30, 2021 at 21:09
  • Related (duplicate?): Redirect the tail output to a file then stop when match found Aug 31, 2021 at 0:10

1 Answer 1

0

With

tail -f /home/user1/logs/application.log |
grep --line-buffered -q 'Application is fully up and running' |
while read ; do pm2 restart cleantmp ; done

you're using -q to tell grep to produce no output and then piping that nothing to a loop that's trying to read it. You could try just this instead:

tail -f /home/user1/logs/application.log |
grep --line-buffered -q -m 1 'Application is fully up and running'
pm2 restart cleantmp

but the tail won't terminate until the next line is written to the input file, which I assume from your problem statement doesn't happen, so you could write an empty line back to the input file from within the script that finds the string you're looking for just before that script exits:

file='/home/user1/logs/application.log'
tail -f "$file" |
awk -v file="$file" '/Application is fully up and running/{exit} END{print "" >> file}'
pm2 restart cleantmp

It's kinda hacky but should work as long as you don't mind a blank line being appended to the input file.

Finally, what I think is the simplest solution, is to forget about tail and just call awk in an infinite loop once per second til the string you want appears then break out of the loop:

while :; do
    awk '/Application is fully up and running/{f=1; exit} END{exit !f}' && break
    sleep 1
done < '/home/user1/logs/application.log'
pm2 restart cleantmp

That last assumes the final message you're looking for gets written to your log file as a single line.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .