13

I'm trying to get the last few lines from journalctl so I can feed them into my conky. However journalctl by default provides too much crap that wastes space: With journalctl -u PROCESS -n 5 --no-pager -l I get entries like:

DATE TIME HOSTNAME PROCESS: MESSAGE

I want to print only TIME MESSAGE. How can I do that?


The manpage says there's an -o argument, but there's no predefined format that fits my need. I tried adding --output-fields=__REALTIME_TIMESTAMP,MESSAGE but that just shows the default output (and not timestamp/message). That argument claims only some formats are affected, so I tried --output-fields=__REALTIME_TIMESTAMP,MESSAGE -o verbose but that only gives me the normal vebose output. Besides, apparently there's 4 fields that are always printed, which is already too many for me. I want just 2: a compact timestamp and the message.

I could use some bash magic or a python script to clean it up, but that seems a bit excessive. Surely there's a way to ask journalctl to give me just a timestamp and message?

3
  • 4
    3 years later, trying to achieve the same behaviour. The --output-fields option is just ignored. Have you solved the issue?
    – Maximko
    Commented Oct 6, 2020 at 8:36
  • @Maximko , have you tried --output="json" --output-fields="MESSAGE", i.e. specifying output explicitly? It works for me where without, --output-fields is indeed ignored. The docs read: Select fields to print in verbose/export/json modes. The default is short, so it doesn't work there.
    – Alex Povel
    Commented Mar 23, 2021 at 20:13
  • I solved the issue using python bindings for systemd, and periodically generating a text file which contains the last 20 lines from journald, formatted as I need (including colored fields, etc.) with conky syntax. I then just read periodically this file in conky.
    – Maximko
    Commented Mar 24, 2021 at 8:54

4 Answers 4

6

journalctl --output cat

cat
               generates a very terse output, only showing the actual message of each journal entry with no metadata, not even a timestamp. If combined with the --output-fields= option will output the listed fields for each log
               record, instead of the message.
1
  • 1
    This doesn't print the timestamp as requested by OP.
    – deanresin
    Commented Nov 11, 2023 at 19:40
3

Surely there's a way to ask journalctl to give me just a timestamp and message?

No. As of now (November 2023) there's no way to have journalctl print just the time and the message without post-processing. The closest to what you want is

journalctl --no-hostname -o short-full

which will give you DATE TIME PROCESS: MESSAGE
If that's not good enough for you then your only option is to use other tools to extract / format that data.
With journalctl you could use one of json or export output modes, extract only the timestamp and message (and convert the timestamp to time only) - like user deanresin shows here via jq.
You could also use one of the systemd bindings available and write your own tool to get that data, as suggested by user Maximko in comments (e.g. python systemd.journal)
Finally, if you wanted to display the messages in real time, you could use journalctl in follow mode and prepend a timestamp each time a line is printed e.g. with ts from moreutils:

journalctl -f -o cat | ts '%H:%M:%S'

Now, as to why --output-fields=__REALTIME_TIMESTAMP,MESSAGE doesn't print only those two fields...

The current manual page for journalctl, section "Output Options" states:

--output-fields=
A comma separated list of the fields which should be included in the output. This has an effect only for the output modes which would normally show all fields (verbose, export, json, json-pretty, json-sse and json-seq), as well as on cat. For the former, the "__CURSOR", "__REALTIME_TIMESTAMP",
"__MONOTONIC_TIMESTAMP", and "_BOOT_ID" fields are always printed.

--output-fields was added in version 236, however support for filtering fields when using -o cat was only added later, in version 246:

journalctl's "-o cat" output mode will now show one or more journal fields specified with --output-fields= instead of unconditionally MESSAGE=. This is useful to retrieve a very specific set of fields without any decoration.

Based on the above, those four fields are always printed except when using -o cat. One would think that

journalctl -o cat --output-fields=__REALTIME_TIMESTAMP,MESSAGE

should work... but that prints

Failed to get data: Invalid argument

Why is that?
The journal fields are described in the man page systemd.journal-fields. There are three timestamp fields for messages: _SOURCE_REALTIME_TIMESTAMP,__REALTIME_TIMESTAMP and __MONOTONIC_TIMESTAMP (note that the last two start with two underscores). All of them are in microseconds, formatted as decimal strings so none of them meets your requirement (HH:MM:SS format). Furthermore, per the same man page, the last two timestamps are special addressing fields (they cannot be used as matches by which to filter the entries):

During serialization into external formats, such as the Journal Export Format or the Journal JSON Format, the addresses of journal entries are serialized into fields prefixed with double underscores. Note that these are not proper fields when stored in the journal but for addressing metadata of entries. They cannot be written as part of structured log entries via calls such as sd_journal_send(3). They may also not be used as matches for sd_journal_add_match(3).

The last sentence points to sd_journal_add_match(3) man page which states:

sd_journal_add_match() adds a match by which to filter the entries of the journal file. Matches applied with this call will filter what can be iterated through and read from the journal file via calls like sd_journal_next(3) and sd_journal_get_data(3). Parameter data must be of the form "FIELD=value", where the FIELD part is a short uppercase string consisting only of 0–9, A–Z and the underscore; it may not begin with two underscores or be the empty string.

hence the error: __REALTIME_TIMESTAMP is not a valid field name for sd_journal_get_data(3).
To sum up: the only timestamp that --output-fields accepts when used together with -o cat is _SOURCE_REALTIME_TIMESTAMP and even then, the output is pretty far from what you want e.g.

journalctl -o cat --output-fields=_SOURCE_REALTIME_TIMESTAMP,MESSAGE

prints

1699815974366491
Supervising 9 threads of 6 processes of 1 users.
1699815968034836
[system] Successfully activated service 'org.kde.powerdevil.backlighthelper'
2

EDIT: Please refer to this answer instead. The below answer is kept only for posterity.


This seems to have been implemented in 2018, see this PR. With version 236 and above it looks like you can use --output-fields=, described in --help. Check your version with systemctl --version, my CentOS 7 currently (in 2019) runs version 219 so this will probably take some time to make it out to most environments.

edit: FYI EL8 (as of 2021-04-12) runs systemd 239, so this is available.

4
  • This is not a qualified answer and only hints at where the answer may be.
    – deanresin
    Commented Nov 11, 2023 at 19:51
  • 1
    As the documentation for --output-fields says that __CURSOR, __REALTIME_TIMESTAMP, __MONOTONIC_TIMESTAMP, and _BOOT_ID are always printed, I don't see how this is an answer to the question.
    – Kusalananda
    Commented Nov 12, 2023 at 7:22
  • @Kusalananda - well, not always - not when using -o cat, though there's a catch here, see my answer. I assume this post was made in good faith, at a time when these options were not properly implemented, nor properly documented and not even available on most platforms - which means it should have been a comment. From what I gather, as I wrote in my post, the answer is clearly "no", the --output-fields option cannot produce the output the OP desires. Commented Nov 13, 2023 at 14:55
  • I have edited the answer to refer to the answer written by @don_crissti instead. Please stop using this comment thread for discussion.
    – pzkpfw
    Commented Nov 14, 2023 at 8:37
2

I'm not convinced it is possible to full fill your requirements using only journalctl, --output, and --output-fields.

You can use the --output=json option of journalctl and then pipe that to jq.

jq is the linux json processor. You can install with sudo apt install jq.

The available fields for --output-fields option are not documented. You can get all the available fields by..

journalctl -n1 --output=json | jq 'keys'.

You can get the timestamp and message only,

journalctl --output=json | jq '.__REALTIME_TIMESTAMP, .MESSAGE'

From there you can format/process further how you want. I would recommend looking at the documentation for jq, man jq.

For example, to get timestamp in human readable you can..

journalctl --output=json | jq '(.__REALTIME_TIMESTAMP | tonumber/1000000 | strflocaltime("%Y-%m-%d %H:%M:%S")), .MESSAGE'

Further, to remove formatting of json and put all on one line like journalctl then..

journalctl --output=json | jq -r '[(.__REALTIME_TIMESTAMP | tonumber/1000000 | strflocaltime("%Y-%m-%d %H:%M:%S")), .MESSAGE] | @tsv'

3
  • +1 though note that the fields are quite well documented, see my answer. Commented Nov 13, 2023 at 14:41
  • In my man journalctl only some fields are mentioned in passing. There is no exhaustive list.
    – deanresin
    Commented Nov 13, 2023 at 23:54
  • 1
    @deanresin the exhaustive list of fields is found here systemd.journal-fields.
    – Eric Mutta
    Commented Mar 1 at 22:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .