1. 程式人生 > >實現Linux tail -f功能

實現Linux tail -f功能

迴圈

這個比較好像,不停的去讀檔案,讀到就打印出來

f = open('a','r')
print(f.read(),end='')
while True:
    try:
        print(f.read(),end='')
    except KeyboardInterrupt:
        f.close()
        break

CPU佔用100%,不是一個好的選擇。

select、poll

一直以來,對select和poll的用法侷限於套接字,實際上,只要是檔案描述符,都可以監控。
select

import select

f = open('a'
,'r') while True: try: rs, ws, es = select.select([f, ], [], []) for i in rs: buf = i.read() print(buf, end='') except KeyboardInterrupt: f.close() break

poll

import select

f = open('a','r')
poller = select.poll()
fd_to_file = {}
poller.register(f,select.POLLIN)
while
True: try: events = poller.poll() for fd,flag in events: if flag and fd == f.fileno(): print(f.read(),end='') except KeyboardInterrupt: f.close() break

然而,CPU佔用率還是100%,原因由於作為一個普通檔案描述符,時刻準備著讀寫事件,這使得select、poll不會阻塞,自然相當於是死迴圈。
此外,epoll不支援監控普通檔案描述符

inotify

Inotify 是一個 Linux特性,它監控檔案系統操作,比如讀取、寫入和建立。Inotify 反應靈敏,用法非常簡單,並且比 cron 任務的繁忙輪詢高效得多。

tail -f實際上就是inotify+select實現的,Python上一個封裝的比較好的庫pyinotify使用的是inotify+epoll,效率自然不低。

# coding=utf-8
import pyinotify


class EventHandler(pyinotify.ProcessEvent):
    """事件處理"""

    def my_init(self, **kargs):
        self.fd = kargs['fd']

    def process_IN_MODIFY(self, event):
        print(self.fd.read(), end='')

path = './a'
f = open(path,'r')
wm = pyinotify.WatchManager()
mask = pyinotify.IN_MODIFY
notifier = pyinotify.Notifier(wm,EventHandler(fd=f))
wm.add_watch(path,mask,auto_add=True,rec=True)
print('now starting monitor %s' % path)
print(f.read(),end='')

while True:
    try:
        notifier.process_events()
        if notifier.check_events():
            notifier.read_events()
    except KeyboardInterrupt:
        notifier.stop()
        break

幾乎看不到CPU佔用,屬上乘。