Open rfxn opened 6 years ago
We could change
printf "%s\n" "1,${trim}d" w | ed -s $inotify_log 2> /dev/null
to instead be
sed "1,${trim}d" $inotify_log > ${inotify_log}_temp 2> /dev/null
cat ${inotify_log}_temp > $inotify_log 2> /dev/null
rm -f ${inotify_log}_temp 2> /dev/null
I have not looked at the internals of how sed works, but since running a "sed -i" results in an inode change, I'm assuming that it's also deleting a file and writing the entirety of the new file to disk. The above adds reading the file contents and then writing them to disk a second time, but allows us to keep the same inode.
Question: What are we trying to achieve by keeping the same inode? I know that changing the inode could break "tail -f" functionality, but I don't see anything in the project that uses "tail -f", and if there are other things that ARE running "tail -f" on these files, would it be possible to change them to "tail -F" instead?
@sporks5000 Effectively that inotifywait writes to an inode; restarting it is significantly time-consuming on some systems.
Oh - I hadn't thought of that. If that's the case, the solution I presented above would potentially run a risk of instances where new lines could be written between between the original read of $inotify_log and the overwrite of $inotify_log. I don't think the risk is huge, but it's definitely worth thinking on to see if there might be another method that would prevent this.
I will keep you posted if I come up with something.
Here's the inotifywait command in the code as it is currently:
$nice_command $inotify -r --fromfile $inotify_fpaths $exclude --timefmt "%d %b %H:%M:%S" --format "%w%f %e %T" -m -e create,move,modify >> $inotify_log 2>&1 &
And here's the inotify log being trimmed in the code as it is currently:
if [ "$log_size" -ge "$inotify_trim" ]; then
trim=$(($log_size - 1000))
log_chars=`printf "%s\n" "1,${trim}p" | ed -s $inotify_log 2> /dev/null | wc -c`
tlog_new=$(( `cat $inspath/tmp/inotify` - $log_chars ))
echo $tlog_new > $inspath/tmp/inotify
printf "%s\n" "1,${trim}d" w | ed -s $inotify_log 2> /dev/null
eout "{mon} inotify log file trimmed"
fi
In order to eliminate our reliance on "ed" we could add the following function:
function log_inotify_out {
local line
while read line; do
if [ -f $trim_inotify_touch ]; then
local log_size=`$wc -l $inotify_log | awk '{print$1}'`
local trim=$(($log_size - 1000))
sed "1,${trim}p" $inotify_log 2> /dev/null | wc -c`
local tlog_new=$(( `cat $inspath/tmp/inotify` - $log_chars ))
echo $tlog_new > $inspath/tmp/inotify
sed -i "1,${trim}d" $inotify_log 2> /dev/null
eout "{mon} inotify log file trimmed"
rm -f $trim_inotify_touch
fi
echo "$line" >> $inotify_log 2>&1
done
}
And then call inotifywait like this
$nice_command $inotify -r --fromfile $inotify_fpaths $exclude --timefmt "%d %b %H:%M:%S" --format "%w%f %e %T" -m -e create,move,modify | log_inotify_out &
And trim the log like this:
if [ "$log_size" -ge "$inotify_trim" ]; then
touch $trim_inotify_touch
fi
Because the echo statement in the function is being called separately for each line, it is re-opening $inotify_log to append to it each time it's given a new line rather than holding it open. As a result, it will not be impacted by changes to the inode that the file exists on. This does have two downsides, though:
@rfxn - What are your thoughts on this? Can you think of any compatibility issues that it might run into?