reads journald *.journal files directly
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-17 21:11:04 +03:00
internal/journal feat: initial 2026-08-17 21:11:04 +03:00
go.mod feat: initial 2026-08-17 21:11:04 +03:00
go.sum feat: initial 2026-08-17 21:11:04 +03:00
main.go feat: initial 2026-08-17 21:11:04 +03:00
output.go feat: initial 2026-08-17 21:11:04 +03:00
README.md feat: initial 2026-08-17 21:11:04 +03:00
timeparse.go feat: initial 2026-08-17 21:11:04 +03:00
timeparse_test.go feat: initial 2026-08-17 21:11:04 +03:00
tty.go feat: initial 2026-08-17 21:11:04 +03:00

lennart

reads journald *.journal files directly. no libsystemd, no systemd, no dbus, just the binary file format parsed in pure go, so log dumps pulled off some other box can be read on whatever machine you happen to have

supports the current on-disk format: the compact layout, keyed hashes, and zstd / lz4 / xz compressed data objects.

build

go build -o lennart .

usage

lennart /path/to/dump                     # everything in a dump directory
lennart -n 50 /path/to/dump               # last 50 entries
lennart -u forgejo -p err -S -2h /dump    # unit + priority + time window
lennart -g 'timeout|refused' -o cat /dump # regexp over MESSAGE, message only
lennart _PID=1 _TRANSPORT=kernel /dump    # arbitrary field matches
lennart -f /var/log/journal               # follow a live journal
lennart --list-boots /dump                # boots present in the dump
lennart --header /dump/system.journal     # journal file header

paths may be files or directories (scanned recursively). with no path given /var/log/journal and /run/log/journal are used. positional arguments containing = are field matches, everything else is treated as a path.

output formats via -o: short (default), short-iso, short-iso-precise, short-precise, short-full, short-unix, short-monotonic, cat, verbose, json, json-pretty, export.

notes

  • multiple files are merged by realtime timestamp, like journalctl --merge.
  • --broken also reads the leftover *.journal~ files journald leaves behind after an unclean shutdown
  • entries are located through the entry array chain, the hash tables are not used, so a partially corrupt file still yields whatever is readable
  • fss sealing (--verify) is not implemented

file format is documented at https://systemd.io/JOURNAL_FILE_FORMAT/.