Golang : simulate tail -f or read last line from log file example
In this tutorial, we will attempt to simulate the Linux/Unix tail
command with -f
option in Golang. What this code example does is to read the entire file line by line until the last line and calculate the last line size.
From the last line size, an offset will be calculated by subtracting the file size by the last line size. After that, we will read from the offset and display the last line content paused by 2 seconds delay. This will simulate the tail -f logfile
command in Golang. Not exactly similar to what you get at http://trac.mondorescue.org/browser/trunk/mindi-busybox/coreutils/tail.c, but this tutorial is here for learning purpose :-)
Here you go!
gotail.go
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"time"
)
var previousOffset int64 = 0
func main() {
flag.Parse()
filename := flag.Arg(0)
delay := time.Tick(2 * time.Second)
for _ = range delay {
readLastLine(filename)
}
}
func readLastLine(filename string) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close()
reader := bufio.NewReader(file)
// we need to calculate the size of the last line for file.ReadAt(offset) to work
// NOTE : not a very effective solution as we need to read
// the entire file at least for 1 pass :(
lastLineSize := 0
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}
lastLineSize = len(line)
}
fileInfo, err := os.Stat(filename)
// make a buffer size according to the lastLineSize
buffer := make([]byte, lastLineSize)
// +1 to compensate for the initial 0 byte of the line
// otherwise, the initial character of the line will be missing
// instead of reading the whole file into memory, we just read from certain offset
offset := fileInfo.Size() - int64(lastLineSize+1)
numRead, err := file.ReadAt(buffer, offset)
if previousOffset != offset {
// print out last line content
buffer = buffer[:numRead]
fmt.Printf("%s \n", buffer)
previousOffset = offset
}
}
Open up 2 terminal windows when you run it for the first time. On one window, run :
>gotail file.log
it will display the last line from the file.log. You can then add additional lines to the bottom of the file.log on another window. The additional lines will appear on the first window where gotail file.log
is executing.
NOTE : Room for improvement. Instead of reading the file every time to get the last line size, try to make it read once.
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+61.4k Golang : Convert HTTP Response body to string
+10.4k Golang : Generate DSA private, public key and PEM files example
+5.1k Golang : Missing Subversion command
+7k Findstr command the Grep equivalent for Windows
+29.2k Golang : How to redirect to new page with net/http?
+5.8k Golang : How to fix html/template : "somefile" is undefined error?
+4.1k Golang : Check if a word is countable or not
+15.4k Golang : How to implement two-factor authentication?
+8.4k Golang : Launch Mac OS X Preview (or other OS) application from your program example
+19k Golang : Secure(TLS) connection between server and client
+16.3k Google Chrome : Your connection to website is encrypted with obsolete cryptography
+7.8k Golang : GMail API create and send draft with simple upload attachment example