首页 > Linux命令大全 > tailf and tail -f

tailf and tail -f

2014年11月3日

tailf and tail -f

http://blogread.cn/it/article/6892
缘起

有一个日志文件,很大很大;当想看最新的写入的时候,首先想到的是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, “a\n”, 8192) = 2
write(1, “a\n”, 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, “a\n”, 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, “a\n”, 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

分类: Linux命令大全 标签: ,
本文的评论功能被关闭了.