tailf 和 tail -f 区别

对于小文件 (大约小于5GB) 使用tailftail -f 没有明显区别。 一次偶然使用tailf查看一个20GB日志文件时, 发现无法显示, 而使用tail -f却可以显示。由此延伸出本文

0x00 准备实验环境


尝试直接google两者的区别发现大部分说的不是很详细,抄的也不是很好。所以自己写下来做个笔记。

1. 生成大文件10GB

使用dd生成指定大小文件
dd if=/dev/urandom of=bigFile bs=10M count=1000

2. 安装strace跟踪进程中的系统函数调用

yum -y install strace

3. 测试载入时间

分别使用 tailftail -f查看刚才生成的文件,明显感觉tailftail -f时间长


0x01 分析两者使用过程中系统调用区别

环境准备
1
2
3
4
5
6
7
echo "test" > test
# 追踪tailf
strace -o trace_tailf tailf test
# 追踪tail -f
strace -o trace_tail_f tail -f test

对比结果:

kionf

从上图可以看出主要有两处不同


test 文件信息
1
2
3
4
5
6
7
8
文件:"test"
大小:5 块:8 IO 块:4096 普通文件
设备:fd01h/64769d Inode:138235 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
最近访问:2018-09-07 17:59:24.842451394 +0800
最近更改:2018-09-07 17:59:19.175452013 +0800
最近改动:2018-09-07 17:59:19.175452013 +0800
创建时间:-


0x02 区别

1. 调用函数区别

使用strace追踪命令的系统函数调用导出文件,分析区别

tailf 流程
1. 使用stat函数获取文件名,fstat通过文件名获取文件 IO block 信息 4096
2. read(3, "test\n", 4096) = 5 #使用read函数从磁盘地址 4096 开始读取文件读取5字节文件大小
tail -f 流程
1. 使用fstat函数通过文件描述符获取信息,获取seek
lseek(3, 0, SEEK_CUR) = 0 #开始seek
lseek(3, 0, SEEK_END) = 5 #结束seek
lseek(3, 0, SEEK_SET) = 0 #当前seek位置
2. seek设置到SEEK_END位置,read函数从末尾读取文件
read(3, "test\n", 5) = 5
lseek(3, 0, SEEK_SET) = 0

通过系统函数调用分析得出区别:

`tailf` :
调用系统函数`stat()`通过获取到的文件名,查看block位置及大小,`read()`从头开始载入指定文件大小块,进行读取
`tail -f` :
调用系统函数`fstat()`获取文件描述符,`lseek()`函数`SEEK_SET`方法移动文件指针到末尾,从末尾`read()`进行读取

系统函数对比:


stat(),fstat()
系统函数:
stat():通过文件名获取文件信息
fstat():通过文件描述符获取文件信息
两者区别:
获取文件信息方式不同
安全问题:
当使用stat()获取文件并打开它时,文件可能会被修改(或权限被更改),或者被符号链接替,fstat()避免了这个问题。


2. 调用函数不同,延伸出的区别

开两个窗口,一个窗口tailf文件,另一个窗口操作文件

[窗口1]>tailf,tail -f 文件
tailf test
# 执行rm,mv 命令后tailf退出查看文件状态
tail -f test
# 执行mv 命令后tail -f继续查看文件,(文件名称改变,文件描述符不变)
# 执行rm 命令后tailf -f继续查看文件,重新创建相同文件名仍然无法查看(因为文件的描述符已经改变)
[窗口]2>更改,删除文件
rm test
mv test test.bak
echo "dddd" > test

由于获取文件信息方式不同(stat通过文件名,fstat通过文件描述符),导致当查看文件被删除时,tailf可以获取到文件被删除,tail -f获取不到。

由于tail -f使用文件描述符,所以即使查看过程中文件名更改tail -f依旧可以获取到文件内容,而tailf 则无法继续查看文件。

共同点:

打印文件后10行,文件增长读取文件。通过linuxstat命令查看文件信息,tailftail -f首次访问会改变文件访问时间,如果文件未改变则不会刷新文件访问时间,文件内容改变会再次访问文件并刷新文件访问时间。


参考:
stat_and_fstat
tailf
tail