tail 是我們大多數人都熟悉的命令。我假設你也熟悉提供的 -f 選項。如果你不熟悉,知道它會列印出文件的最後幾行即可。最近在一個項目上工作,我想知道我需要做什麼來實現這個功能。這個想法來自閱讀 Feynman 的書:
毫無疑問,你知道如何去做; 但是當你像小孩子一樣玩這類問題,並且你沒有看到答案時...試圖找出如何去做是很有趣的。然後,當你進入成年時,你會培養出一定的自信,你可以去發現事物; 但是如果他們已經被發現,那你根本不應該再來打擾自己。一個傻瓜能做的事,另一個傻瓜也能做,其他一些傻瓜打你的事實不應該打擾你:你應該為將要發現的事物而快樂。
實現它可能是一件小事。但我認為這將是一系列文章中的一個良好的開端,在這篇文章中我寫了如何實現一些東西。因此,讓我帶你看看如何在 Go 中實現 tail -f 的過程。
首先,讓我們了解這個問題。tail 命令提供了一個標誌,可以「跟蹤」文件。它所做的是等待添加到文件末尾的任何更改並將其列印出來。為了簡單起見,我不打算實現 tail,而只是實現跟蹤功能。 所以我們在開始時列印整個文件,然後在添加它們時列印行。
我首先想到的是這樣做的非常幼稚的方式。 列印文件中的所有位元組,直到達到 io.EOF; 讓這個過程睡一會兒,然後再試一次。 我們來看看這個函數:
當內容寫入文件時,可悲的是沒有及時做出反應。Linux 提供了一個 API 來監視文件系統事件:inotify AP。手冊頁給了你一個很好的介紹。它提供了兩個我們感興趣的函數:inotify_init 和 inotify_add_watch。inotify_init 函數創建一個對象,我們將使用該對象進一步與 API 進行交互。inotify_add_watch 函數允許你指定感興趣的文件事件。API 提供了幾個事件,但我們關心的是修改文件時發出的 IN_MODIFY 事件。
由於我們使用Go,不得不列出 syscall 包。它為前面提到的功能提供了包裝器:syscall.InotifyInit 和 syscall.InotifyAddWatch。使用 syscall 讓我們看看如何實現 follow 函數。為了簡潔起見,我省略了錯誤處理,當你看到一個 _ 變量被使用時,它是處理返回錯誤的好地方。
InotifyInit 函數返回一個可用於讀取 sycall.InotifyEvent 的文件處理程序。從這個處理程序讀取是一個阻塞操作。 這使我們只有在創建事件時才做出反應。
如果您要處理多個作業系統,最好更一般地處理這個作業系統。這就是 fsnotify 軟體包的來源。它提供了一個針對 Linux 的 inotify,BSD 的 kqueue 等的抽象。使用 fsnotify 我們的函數看起來與前面的非常相似,但是更簡單。
我希望代碼解釋得比我寫的文本更好。 為了簡潔,我省略了代碼可能失敗的幾種情況。 為了完善功能,我必須深入挖掘。 但這足以讓我對其產生了知識的渴望:它到底是如何工作的。希望你也由此感覺。
via: http://satran.in/2017/11/15/Implementing_tails_follow_in_go.html
作者:Satyajit Ranjeev 譯者:shniu 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出