Tags

, ,

“tail -f” is a special command in a way that it polls the specified file for any change and prints the new stuff on the fly. It is very helpful in observing logs and any event based data.

Ever wondered how tail achieves this?

“tail” opens the given file and obtains the file-descriptor. It opens it with xfreopen() -> freopen() -> fopen() call. It does its first round of fstat() on the file as well.

Once it has got the fd, it loops infinitely and do the following:

It does fstat() of the file and observes the mtime value. If the mtime value is changes from the last time..it dumps the data. To print the latest data, it lseek() the file to the last reported file size.

Source: http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/tail.c

A strace of tail on my Ubuntu 11.04 is as follows:

kanaujia@ubuntu:~/Desktop/FUSE/dedup$ strace tail -f ./file.py 
execve("/usr/bin/tail", ["tail", "-f", "./file.py"], [/* 38 vars */]) = 0
brk(0)                                  = 0x9567000
[....]
open("./file.py", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=103, ...}) = 0
_llseek(3, 0, [0], SEEK_CUR)            = 0
_llseek(3, 0, [103], SEEK_END)          = 0
_llseek(3, 0, [0], SEEK_SET)            = 0
read(3, "FILE = open('./myfs/dood',\"w\")\np"..., 103) = 103
_llseek(3, 0, [0], SEEK_SET)            = 0
read(3, "FILE = open('./myfs/dood',\"w\")\np"..., 103) = 103
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb775c000
[...]
fstat64(3, {st_mode=S_IFREG|0644, st_size=103, ...}) = 0
fstatfs64(3, 84, {f_type="EXT2_SUPER_MAGIC", f_bsize=4096, f_blocks=4902319,
         f_bfree=3748629, f_bavail=3499605, f_files=1245184, f_ffree=1041484,
         f_fsid={598995932, 149996801}, f_namelen=255, f_frsize=4096}) = 0
inotify_init()                          = 4
inotify_add_watch(4, "./file.py", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = 1
fstat64(3, {st_mode=S_IFREG|0644, st_size=103, ...}) = 0
read(4, ....

So, it is using fstat and inotify API that add a watch to an initialized inotify instance.

Advertisements