I've got log files which get downloaded via cron job. If a file is updated on the remote location, the local copy gets rewritten from the beginning even if only data has been appended.
Tools like tail -f
or since
seem to see this as "the file has been replaced" and start outputting them from the beginning again. i.e. repeat all already known content. Especially those two tools explicitly mention this on STDERR.
So if I call this in one terminal:
for j in $(seq 2 4) ; do for i in $(seq 1 $j) ; do echo $i ; sleep 1; done > /tmp/foo; done
I get these warnings with both, tail -f /tmp/foo
and tail -F /tmp/foo
in another terminal:
1
2
tail: /tmp/foo: file truncated
1
2
3
tail: /tmp/foo: file truncated
1
2
3
4
And with while sleep 0.25; do since /tmp/foo; done
, I get one of these error messages:
1
2
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
since: considering /tmp/foo to be truncated, displaying from start
1
2
3
4
since
explicitly uses the inode and not the file name as key for a file. tail
probably does something similar to recognise truncated files.
Another "tool" I tried is the Perl library File::Tail, but it has the same "issue", just without warnings (at least with default settings).
So I wonder: Is a way or tool which does not look at the inode but just at the contents of the file and only restarts if data has not just been appended?
What I would like to have is just this output:
1
2
3
4
(I've seen tail -f, but when the file is deleted and re-created (not appended), but it does not help as it still restarts outputting the file's content from the beginning as well.)
And yes, I'm aware that such a tool either needs a cache of all seen (but not truncated) data or at least hashsums of it.
tail -n +$(( N + 1)) file
into a variable,wc -l
the new lines, add that to N, and write the new lines to your output stream. Thensleep 10
(or some compromise between acceptable delay and acceptable workload) and repeat. You need some strategy to reset N=0 if the file is actually truncated at the server.since
uses the inode as the key, than don't change the inode. When you update the file, instead of copying it directly to the same file, copy it first to a temporary file, and then copy it back to the original file. It's inode will not be changed. In that case the inode won't change andsince
will work.since
since (sic!) this is what I'd prefer here. But I need something in short term, too.