Reputation: 1
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
Reputation: 26471
The piece of code provided by in the OP never finishes because of the following reason:
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.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)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
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
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