Note that this document describes the binary serialization format of journals only, as used for transfer across the network. For interfacing with web technologies there's the Journal JSON Format, described below. The binary format on disk is documented as the Journal File Format.
Before reading on, please make sure you are aware of the basic properties of journal entries, in particular realize that they may include binary non-text data (though usually don‘t), and the same field might have multiple values assigned within the same entry (though usually hasn’t).
When exporting journal data for other uses or transferring it via the network/local IPC the journal export format is used. It's a simple serialization of journal entries, that is easy to read without any special tools, but still binary safe where necessary. The format is like this:
__CURSOR=
, __REALTIME_TIMESTAMP=
, __MONOTONIC_TIMESTAMP=
are introduced this way. Note that these meta-fields are only generated when actual journal files are serialized. They are omitted for entries that do not originate from a journal file (for example because they are transferred for the first time to be stored in one). Or in other words: if you are generating this format you shouldn't care about these special double-underscore fields. But you might find them usable when you deserialize the format generated by us. Additional fields prefixed with two underscores might be added later on, your parser should skip over the fields it does not know.This format can be generated via journalctl -o export
.
Here's an example for two serialized entries which consist only of text data:
__CURSOR=s=739ad463348b4ceca5a9e69c95a3c93f;i=4ece7;b=6c7c6013a26343b29e964691ff25d04c;m=4fc72436e;t=4c508a72423d9;x=d3e5610681098c10;p=system.journal __REALTIME_TIMESTAMP=1342540861416409 __MONOTONIC_TIMESTAMP=21415215982 _BOOT_ID=6c7c6013a26343b29e964691ff25d04c _TRANSPORT=syslog PRIORITY=4 SYSLOG_FACILITY=3 SYSLOG_IDENTIFIER=gdm-password] SYSLOG_PID=587 MESSAGE=AccountsService-DEBUG(+): ActUserManager: ignoring unspecified session '8' since it's not graphical: Success _PID=587 _UID=0 _GID=500 _COMM=gdm-session-wor _EXE=/usr/libexec/gdm-session-worker _CMDLINE=gdm-session-worker [pam/gdm-password] _AUDIT_SESSION=2 _AUDIT_LOGINUID=500 _SYSTEMD_CGROUP=/user/lennart/2 _SYSTEMD_SESSION=2 _SELINUX_CONTEXT=system_u:system_r:xdm_t:s0-s0:c0.c1023 _SOURCE_REALTIME_TIMESTAMP=1342540861413961 _MACHINE_ID=a91663387a90b89f185d4e860000001a _HOSTNAME=epsilon __CURSOR=s=739ad463348b4ceca5a9e69c95a3c93f;i=4ece8;b=6c7c6013a26343b29e964691ff25d04c;m=4fc72572f;t=4c508a7243799;x=68597058a89b7246;p=system.journal __REALTIME_TIMESTAMP=1342540861421465 __MONOTONIC_TIMESTAMP=21415221039 _BOOT_ID=6c7c6013a26343b29e964691ff25d04c _TRANSPORT=syslog PRIORITY=6 SYSLOG_FACILITY=9 SYSLOG_IDENTIFIER=/USR/SBIN/CROND SYSLOG_PID=8278 MESSAGE=(root) CMD (run-parts /etc/cron.hourly) _PID=8278 _UID=0 _GID=0 _COMM=run-parts _EXE=/usr/bin/bash _CMDLINE=/bin/bash /bin/run-parts /etc/cron.hourly _AUDIT_SESSION=8 _AUDIT_LOGINUID=0 _SYSTEMD_CGROUP=/user/root/8 _SYSTEMD_SESSION=8 _SELINUX_CONTEXT=system_u:system_r:crond_t:s0-s0:c0.c1023 _SOURCE_REALTIME_TIMESTAMP=1342540861416351 _MACHINE_ID=a91663387a90b89f185d4e860000001a _HOSTNAME=epsilon
A message with a binary field produced by
python3 -c 'from systemd import journal; journal.send("foo\nbar")' journalctl -n1 -o export
__CURSOR=s=bcce4fb8ffcb40e9a6e05eee8b7831bf;i=5ef603;b=ec25d6795f0645619ddac9afdef453ee;m=545242e7049;t=50f1202 __REALTIME_TIMESTAMP=1423944916375353 __MONOTONIC_TIMESTAMP=5794517905481 _BOOT_ID=ec25d6795f0645619ddac9afdef453ee _TRANSPORT=journal _UID=1001 _GID=1001 _CAP_EFFECTIVE=0 _SYSTEMD_OWNER_UID=1001 _SYSTEMD_SLICE=user-1001.slice _MACHINE_ID=5833158886a8445e801d437313d25eff _HOSTNAME=bupkis _AUDIT_LOGINUID=1001 _SELINUX_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 CODE_LINE=1 CODE_FUNC=<module> SYSLOG_IDENTIFIER=python3 _COMM=python3 _EXE=/usr/bin/python3.4 _AUDIT_SESSION=35898 _SYSTEMD_CGROUP=/user.slice/user-1001.slice/session-35898.scope _SYSTEMD_SESSION=35898 _SYSTEMD_UNIT=session-35898.scope MESSAGE ^G^@^@^@^@^@^@^@foo bar CODE_FILE=<string> _PID=16853 _CMDLINE=python3 -c from systemd import journal; journal.send("foo\nbar") _SOURCE_REALTIME_TIMESTAMP=1423944916372858
Note that this section describes the JSON serialization format of the journal only, as used for interfacing with web technologies. For binary transfer of journal data across the network there's the Journal Export Format described above. The binary format on disk is documented as Journal File Format.
Before reading on, please make sure you are aware of the basic properties of journal entries, in particular realize that they may include binary non-text data (though usually don‘t), and the same field might have multiple values assigned within the same entry (though usually hasn’t).
In most cases the Journal JSON serialization is the obvious mapping of the entry field names (as JSON strings) to the entry field values (also as JSON strings) encapsulated in one JSON object. However, there are a few special cases to handle:
__CURSOR
, __REALTIME_TIMESTAMP
, __MONOTONIC_TIMESTAMP
, which contain the cursor string of this entry as string, and the realtime/monotonic timestamps of this entry as formatted numeric string of usec since the respective epoch.Here's an example, illustrating all cases mentioned above. Consider this entry:
MESSAGE=Hello World _UDEV_DEVNODE=/dev/waldo _UDEV_DEVLINK=/dev/alias1 _UDEV_DEVLINK=/dev/alias2 BINARY=this is a binary value \a LARGE=this is a super large value (let's pretend at least, for the sake of this example)
This translates into the following JSON Object:
{ "MESSAGE" : "Hello World", "_UDEV_DEVNODE" : "/dev/waldo", "_UDEV_DEVLINK" : [ "/dev/alias1", "/dev/alias2" ], "BINARY" : [ 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 98, 105, 110, 97, 114, 121, 32, 118, 97, 108, 117, 101, 32, 7 ], "LARGE" : null }