最新消息:

tailf and tail -f

Linux admin 6430浏览 0评论

缘起

   有一个日志文件,很大很大;当想看最新的写入的时候,首先想到的是tailf,大概是因为 tailf 比 tail -f 少2个字符吧。但是,许久没有输出,感觉不应该的,不管文件有多大,从文件尾部开始查还是比较快的;换用tail -f 试试,很快就出结果了。

下面就谈谈二者的区别:

   1. tailf 总是从文件开头一点一点的读, 而tail -f 则是从文件尾部开始读

   2. tailf check文件增长时,使用的是文件名, 用stat系统调用;而tail -f 则使用的是已打开的文件描述符; 注:tail 也可以做到类似跟踪文件名的效果; 但是tail总是使用fstat系统调用,而不是stat系统调用;结果就是:默认情况下,当tail的文件被偷偷删除时,tail是不知道的,而tailf是知道的。

关于stat & fstat

   fstat与 stat() 函数相似,不同的是,它是作用于已打开的文件指针而不是文件名

关于 tail -F filename

-F filename  是跟踪文件名,当文件被删除或被重新创建是可以立即(伪立即)发现的。实现逻辑如下:

   如果filename被打开了,不是每次都重新打开文件,而是用fstat检查文件是否变化,隔几次才使用open方法检查文件是否还在,如果成功打开了,则fstat检查一下是否依然是原来的那个文件,如果是,则直接关闭本次的文件描述符,依然使用原来的监视;如果不是,则开始监视新的文件,strace跟踪如下:

   strace -F a

open("a", O_RDONLY|O_NONBLOCK)          = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
lseek(3, 0, SEEK_SET)                   = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
read(3, "an", 8192)                    = 2
write(1, "an", 2a
)                      = 2
read(3, "", 8192)                       = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
open("a", O_RDONLY|O_NONBLOCK)          = 4
fstat(4, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
close(4)                                = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({1, 0}, NULL)                 = 0

tail -retry 选项是干啥的

   默认情况下, tail -f filename 当filename不存在时,则直接退出; 但是,如果使用-retry选项,则会不断尝试打开该文件,而不是直接退出,这在有时候是有用的

strace tailf

open("a", O_RDONLY)                     = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2af8e0b98000
read(3, "an", 4096)                    = 2
read(3, "", 4096)                       = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2af8e0b99000
write(1, "an", 2a
)                      = 2
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0
stat("a", {st_mode=S_IFREG|0664, st_size=2, ...}) = 0
nanosleep({0, 250000000}, NULL)         = 0

   参考资料:

   http://codingstandards.iteye.com/blog/832760

 

转载请注明:爱开源 » tailf and tail -f

您必须 登录 才能发表评论!