mattman71465
mattman71465

Reputation: 1

Check if a file has updated

I am trying to check to see if a file (in this case /var/log/messages) has been updated using 'stat' command in a loop. However the code never exits the loop and moves on for some reason.

#!/bin/bash 
check='/var/log/messages'

THEN="stat -c %z ${check}"
NOW="stat -c %z ${check}"

while [ $"NOW" == $"THEN" ]
do 

    echo "$NOW"
if [ $"NOW" != $"THEN" ]; then 
    echo "${check} has been updated."

if 

done

Thoughts on this? Is there an easier way to see if /var/log/messages has changed?

Upvotes: 0

Views: 1540

Answers (3)

kvantour
kvantour

Reputation: 26471

The piece of code provided by in the OP never finishes because of the following reason:

  1. the variables NOW and THEN are never updated inside of the while-loop. As they never update, the loop continues to run as both values are identical.
  2. the variables NOW and THEN represent the status change and not the modification change. The time of status-change is the time when the meta-data of the file has changed (permissions, groups, ...). The user might be more interested in looking at the content change (modification change)
  3. the variables NOW and THEN actually are not the output of the stat command, but just the command itself since they are not executed using $(stat ...).

An update to the code would be:

#!/usr/bin/env bash 
check_file="/var/log/messages"

THEN="$(stat -c "%Y" "${check_file}")"
NOW="$(stat -c "%Y" "${check_file}")"


while [ "$NOW" = "$THEN" ]; do
   # Sleep a second to have some waiting time between checks
   sleep 1
   # Update now
   NOW="$(stat -c "%Y" ${check_file}")"
done
echo "${check_file} has been modified"

This can be simplified to

#!/usr/bin/env bash 
check_file="/var/log/messages"

THEN="$(stat -c "%Y" "${check_file}")"

while [ "$(stat -c "%Y" ${check_file}")" = "$THEN" ]; do
   # Sleep a second to have some waiting time between checks
   sleep 1
done
echo "${check_file} has been modified"

However, it might be easier to use bash-interals and check modification by comparing files-dates

#!/usr/bin/env bash
touch tmpfile
while [ tmpfile -nt /var/log/messages ]; do sleep 1; done
echo "/var/log/messages has been modified"
rm tmpfile

This method is unfortunately fairly impractical. If you want to monitor if a file has been updated, especially in case of log-file where lines are appended, you can just use tail. The command will print out the new lines which are appended the moment a file is updated.

$ tail -f -- /var/log/messages

If you don't want to monitor updates to log-files but just want to check if a file is updated, you can use inotify-wait:

$ inotifywait -e modify /var/log/messages

Upvotes: 0

Khanna111
Khanna111

Reputation: 3913

Firstly the version below in the least executes the stat command plus all the changes that are explained above. One thing that you would have to think about is the then and now would almost always be the same unless the messages is being updated in less then the time it takes to execute

#!/bin/bash
check='/var/log/messages'

THEN=`stat -c %z ${check}`
NOW=`stat -c %z ${check}`

if [ "$NOW" == "$THEN" ]; then

    echo "$NOW"
elif [ "$NOW" != "$THEN" ]; then
    echo "$check has been updated."
fi
~   

Note the fact that the stat is being executed.

Upvotes: 0

chepner
chepner

Reputation: 531055

The dollar signs need to be inside the quotes. $"..." is a special quoting mechanism for doing translations, so unless you are using a locale in which NOW and THEN translate to the same string, the condition will never be true.

if [ "$NOW" == "$THEN" ]; then

Upvotes: 1

Related Questions