// 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) } }