4

I am wondering if the default output for journalctl can be adjusted. Such that a custom pattern can be supplied.

For example I would like to:

  • display the log level (e.g. priority)
  • configure fixed column width for certain journal fields
  • enable output coloring

I am used to the capabilities that Java logging frameworks such as Log4j2 provide where I can simply specify a log pattern to adjust the output format of log messages. Does journalctl support such a mechanism?

Note: I am aware of the -o, --output= option but I am looking for something more fine grained.

lanoxx
  • 302
  • 1
  • 4
  • 12

2 Answers2

3

No. journalctl is a query tool, not a formatting tool. It has some formatting options, but it is not log4j2. DigitalOcean has a nice writeup:

https://www.digitalocean.com/community/tutorials/how-to-use-journalctl-to-view-and-manipulate-systemd-logs

journalctl json output piped to jq may be sufficient.

Jonah Benton
  • 1,252
  • 7
  • 13
1

I wrote my own Shell function which can provide what you asked for.

function rl() {
    ## rl: read log
    ## journalctl wrapper with nice output format and colors based on log event severity.
    ## The order is for human consumption only so they are just based on RFC 5424 (without being compliant) and the default journalctl short-iso format.
    ## The syslog severity is added. This one is missing in all common log formats or not human readable (RFC 5424).
    ## The time format is based on systemd.time(7) and RFC 3339.
    ## The colors are made up by ypid because I could not find a proper standard.
    ## Ref: https://serverfault.com/questions/59262/bash-print-stderr-in-red-color/502019#502019
    ## Ref: https://serverfault.com/questions/801514/systemd-default-log-output-format

    # shellcheck disable=SC2016
    command journalctl "$@" -o json \
        | jq --unbuffered --raw-output '"echo \(.PRIORITY|tonumber|@sh) \"$(date --date @\((._SOURCE_REALTIME_TIMESTAMP // .__REALTIME_TIMESTAMP) |tonumber | ./ 1000000 | tostring) '\''+%F %T %Z'\'')\" \(._HOSTNAME|@sh) \(.SYSLOG_IDENTIFIER|@sh): \(.MESSAGE | gsub("\n"; "\n    ") | @sh) "' \
        | sh \
        | perl -e 'my $c_to_sev = {0 => "48;5;9", 1 => "48;5;5", 2 => "38;5;9", 3 => "38;5;1", 4 => "38;5;5", 5 => "38;5;2", 6 => "38;5;2"}; while (<>) { s#^(([0-6])(?: [^ ]+){5})(.*)#\e[$c_to_sev->{$2}m$1\e[m$3#; print; }'
}

(Or checkout https://github.com/ypid/scripts/blob/master/rl)

I agree that it looks a bit cryptic and is a bit slower than using journalctl directly. So you might want to first use journalctl with paging to find what you are looking for and then use rl with a filter. Because I did not fine a way around generating shell commands based on the log fields and EXECUTING it, I put some thought into ensuring that you cannot get remote code execution using male formated logs. If you find a way please let me know ;-)

An example output line looks line this:

6 2019-09-06 00:01:55 CEST debops-dev-deb-10 systemd: Starting Daily man-db regeneration...
ypid
  • 171
  • 1
  • 4