72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
|
// SPDX-License-Identifier: MIT
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"os/signal"
|
||
|
"syscall"
|
||
|
|
||
|
"github.com/alexjch/go-dmesg/pkg/dmesg"
|
||
|
"github.com/gokrazy/gokrazy"
|
||
|
)
|
||
|
|
||
|
// Primitives are:
|
||
|
// - scanner, a bufio.Scanner that reads from /dev/kmsg
|
||
|
// - decoder, a dmesg.Decoder that wraps a scanner and decodes log records
|
||
|
// {decoder{scanner}}}
|
||
|
var LEVELS = map[uint8]string{
|
||
|
0: "Emergency",
|
||
|
1: "Alert",
|
||
|
2: "Critical",
|
||
|
3: "Error",
|
||
|
4: "Warning",
|
||
|
5: "Notice",
|
||
|
6: "Info",
|
||
|
7: "Debug",
|
||
|
}
|
||
|
|
||
|
func NewScanner() (*dmesg.Scanner, error) {
|
||
|
// Open /dev/kmsg for reading in a non-blocking manner
|
||
|
f, err := os.OpenFile("/dev/kmsg", syscall.O_RDONLY|syscall.O_NONBLOCK, 0)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("Failed to open kernel log: %w", err)
|
||
|
}
|
||
|
f.Seek(0, 3)
|
||
|
// Wrap an os.File in a bufio.Scanner
|
||
|
scanner := bufio.NewScanner(f)
|
||
|
return &dmesg.Scanner{
|
||
|
Scanner: *scanner,
|
||
|
ReadCloser: f,
|
||
|
}, nil
|
||
|
}
|
||
|
func main() {
|
||
|
gokrazy.WaitForClock()
|
||
|
// Handle Ctrl-C
|
||
|
c := make(chan os.Signal, 1)
|
||
|
signal.Notify(c, os.Interrupt)
|
||
|
// Create a scanner
|
||
|
scan, err := NewScanner()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
defer scan.Close()
|
||
|
// Create a decoder
|
||
|
dec, err := dmesg.NewDecoder(scan)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
// Stop the decoder when Ctrl-C is pressed
|
||
|
go func() {
|
||
|
<-c
|
||
|
dec.Stop()
|
||
|
}()
|
||
|
// Follow the decoder until Ctrl-C is pressed
|
||
|
if err := dec.Follow(func(r *dmesg.Record) {
|
||
|
fmt.Printf("%9s: %v: %s\n", LEVELS[r.Priority], r.Timestamp, r.Message)
|
||
|
}); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|