8

According to the systemd docs, journalctl is recommended for browsing logs, rather than the /var/log/* file tree.

While man 1 journalctl describes how to use it, I still don't know what arguments it needs to give me the list of stuff I want. For example, I want to see a list of user logins. I'm aware sshd handles ssh logins, but what about local logins and general user authentication?

Here's what I've tried:

#shows all logs. huge
journalctl

#limit history and search for "login"
journalctl --since "yesterday" | grep login

#a week ago rather than just a day
journalctl --since `date +"%Y-%m-%d" --date "last week"` | grep login

... systemd-logind[678]: New session 81 of user jozxyqk.

This seems to give some indications but definitely not the most robust method. What's the correct way?

4

3 Answers 3

6

Run:

journalctl -q _AUDIT_TYPE=1112 _TRANSPORT=audit

Explanation:

Assuming you have the audit subsystem running (and unless you disabled it, you do), that's the best way to get this kind of information, because among other things if you use _TRANSPORT=audit, messages can't be spoofed like those over the traditional syslog socket. To see all of the messages sent through this transport, use journalctl -q _TRANSPORT=audit. (The -q keeps out annoying -- Reboot -- lines.)

To see these in verbose form, do journalctl -q _TRANSPORT=audit -o verbose. Actually, I suggest stopping and doing that right now as you're following along, because the next thing we want to do is to filter on one some of the fields we see there. Here's a record from my system:

_BOOT_ID=[redacted]
_MACHINE_ID=[redacted]
_HOSTNAME=[redacted]
_UID=0
_TRANSPORT=audit
SYSLOG_FACILITY=4
SYSLOG_IDENTIFIER=audit
AUDIT_FIELD_HOSTNAME=?
AUDIT_FIELD_ADDR=?
AUDIT_FIELD_RES=success
_AUDIT_LOGINUID=18281
_AUDIT_TYPE=1112
AUDIT_FIELD_OP=login
AUDIT_FIELD_ID=18281
_PID=5398
_SELINUX_CONTEXT=system_u:system_r:local_login_t:s0-s0:c0.c1023
AUDIT_FIELD_EXE=/usr/bin/login
AUDIT_FIELD_TERMINAL=tty6
_AUDIT_SESSION=541
_SOURCE_REALTIME_TIMESTAMP=1480529473269000
_AUDIT_ID=7444
MESSAGE=USER_LOGIN pid=5398 uid=0 auid=18281 ses=541 subj=system_u:system_r:local_login_t:s0-s0:c0.c1023 msg='op=login id=18281 exe="/usr/bin/login" hostname=? addr=? terminal=tty6 res=success'

The MESSAGE at the bottom is the unstructured log record, which is basically what you see in the non-verbose syslog-style output. We could grep for MESSAGE=USER_LOGIN (and be done right now) but the journal lets us do more cool stuff, so let's keep at it.

Each audit message type has an associated _AUDIT_TYPE (imagine that!). For some reason, this doesn't get helpfully converted to text in the structured output, but 1112 corresponds to USER_LOGIN. I confirmed this by checking in libaudit.h, which has (with some context lines):

#define AUDIT_USER_CHAUTHTOK    1108    /* User acct password or pin changed */
#define AUDIT_USER_ERR          1109    /* User acct state error */
#define AUDIT_CRED_REFR         1110    /* User credential refreshed */
#define AUDIT_USYS_CONFIG       1111    /* User space system config change */
#define AUDIT_USER_LOGIN        1112    /* User has logged in */
#define AUDIT_USER_LOGOUT       1113    /* User has logged out */
#define AUDIT_ADD_USER          1114    /* User account added */
#define AUDIT_DEL_USER          1115    /* User account deleted */

so, journalctl -q _AUDIT_TYPE=1112 _TRANSPORT=audit is what you need. It gets ssh, terminal, and GUI logins, and records success and failure. Note that it doesn't catch things like sudo or su — there are different audit records for those.

Even the "short" version of the output is kind of verbose, so you might want to use -o json and create a short script to parse the output into a pretty format.

4
journalctl -q SYSLOG_FACILITY=10 SYSLOG_FACILITY=4

This tells journal to filter out messages coming from 2 different facilities. Number 10 for authpriv and number 4 for auth. ssh as well as many other login sensitive applications use these 2 facilities to log.

1

Do you want logins or login attempts?

This shows logins but not attempts (today for example) and works in Fedora 22:

$ journalctl -u 'systemd-logind'  --since "today" --until "tomorrow"

Here is sample output: -- Logs begin at Mon 2014-09-01 03:10:03 BST, end at Fri 2015-11-20 09:55:02 GMT. -- Nov 20 08:47:15 meow systemd[1]: Starting Login Service... Nov 20 08:47:15 meow systemd-logind[699]: New seat seat0. Nov 20 08:47:15 meow systemd-logind[699]: Watching system buttons on /dev/input/event2 (Power Button) Nov 20 08:47:15 meow systemd-logind[699]: Watching system buttons on /dev/input/event0 (Power Button) Nov 20 08:47:15 meow systemd-logind[699]: Watching system buttons on /dev/input/event1 (Lid Switch) Nov 20 08:47:15 meow systemd[1]: Started Login Service. Nov 20 08:47:37 meow systemd-logind[699]: New session c1 of user gdm. Nov 20 08:47:46 meow systemd-logind[699]: New session c2 of user gdm. Nov 20 08:47:46 meow systemd-logind[699]: Removed session c1. Nov 20 08:47:46 meow systemd-logind[699]: Removed session c2. Nov 20 08:47:46 meow systemd-logind[699]: New session c3 of user gdm. Nov 20 08:51:22 meow systemd-logind[699]: New session 1 of user david1.

It is cluttered with other info such as the lid and power buttons, so you could grep for session to be more precise: $ journalctl -u 'systemd-logind' --since "today" --until "tomorrow" | grep session Nov 20 08:47:37 meow systemd-logind[699]: New session c1 of user gdm. Nov 20 08:47:46 meow systemd-logind[699]: New session c2 of user gdm. Nov 20 08:47:46 meow systemd-logind[699]: Removed session c1. Nov 20 08:47:46 meow systemd-logind[699]: Removed session c2. Nov 20 08:47:46 meow systemd-logind[699]: New session c3 of user gdm. Nov 20 08:51:22 meow systemd-logind[699]: New session 1 of user david1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.