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
+8.7k Golang : Populate or initialize struct with values example
+9.1k Golang : Web(Javascript) to server-side websocket example
+10.6k Golang : Removes punctuation or defined delimiter from the user's input
+13.2k Golang : Qt progress dialog example
+14.3k Golang : Rename directory
+13.8k Javascript : Prompt confirmation before exit
+21.5k Golang : Use TLS version 1.2 and enforce server security configuration over client
+8.8k Golang : Intercept and compare HTTP response code example
+15.3k Golang : Validate hostname
+11.4k Golang : Convert(cast) float to int
+10.3k Golang : Bubble sort example
+11.2k Golang : Handle API query by curl with Gorilla Queries example