The Unix login database

The Unix login database has been a part of Unix since the 1970s. It existed in BSD version 1 in 1977 and in Research UNIX Version 7 in 1979. It is a binary database with (nowadays) three tables that stores information about interactive login sessions as they come and go on the system.

The BSDs and Linux operating systems all possess it.

The database files

The database on modern Unices and Linux operating systems comprises three files, each of which is a single database table. There are no index files, and each table file comprises a sequence of fixed-length database records.

The table of active login sessions

This gives a snapshot of what login sessions are actually active at the moment. Entries are written here when login sessions begin and end. This table is non-persistent, first by dint of living on a filesystem that it not persistent, and second by dint of being emptied of all records as part of system startup and shutdown.

The table of active login sessions on FreeBSD and its derivatives

Operating systems such as FreeBSD have a simple system for this table. It is driven from a PAM plug-in module named pam_lastlog, which is invoked when PAM sessions are created and destroyed by the login program. The SSH server does much the same, but replicates what the PAM module does internally, itself, rather than using the PAM module.

Thus there are only two types of entry in this table; and they are created and destroyed symmetrically by the same process, the process that is performing the PAM, or SSH, session management. (Contrary to folklore, process #1 does not touch the login database at all.) Moreover, process IDs in this table are not those of the actual session leader processes in the login session, but of their various parent processes that spawned them.

The FreeBSD manual claims that it restricts indefinite table growth by re-using stale entries in the table wherever possible. In fact, it does not. The mechanism that it uses is somewhat thwarted by the PAM plug-in module assigning a new pseudo-random "id" value to each PAM session, meaning that existing stale "user" entries are not re-used in practice, only "dead" entries.

The table of active login sessions on Linux operating systems

Linux operating systems that have historically used the obsolete van Smoorenburg clone of the AT&T System 5 unix inittab mechanism have a more complex system for this table. It contains many types of entry, some of which are also obsolete. The system is further confounded by local TUI login via the login program, remote login via an SSH server, local GUI login, and GUI terminal emulators running "login" shells, all having significantly different behaviours from one another.

For real terminal or virtual terminal login services that invoke the login program, the modern behaviour (as opposed to the obsolete van Smoorenburg behaviour) is as follows:

For remote login services, the somewhat different behaviour is:

For GUI login services for subsystems like GNOME or MATE, the further different behaviour is:

For GUI terminal emulators running "login" shells, the yet further different behaviour is:

This mess results in a mess.

The log of login events

This is a binary log of all login session events that just grows indefinitely until trimmed. It it stored on persistent storage and is not wiped at either bootstrap or shutdown. With it, one can determine when a system was bootstrapped and shutdown, any major clock change events (major enough to affect a log of login sessions), and a sequence of logon and logoff events.

On FreeBSD and its derivatives, this contains "boot", "shutdown", "old time", "new time", "user", and "dead" entries.

On Linux operating systems, this contains "init", "getty", "login", "user", "dead", "boot", "old time", "new time", and "runlevel" entries.

The program that is run at bootstrap, before entering normal (a.k.a. "multi-user") mode, and as part of transitioning to shutdown mode, is something such as utx, systemd-update-utmp, or login-update-utmpx.

The table of last account logins

This gives a snapshot of the last login session start time for all accounts on the system.

On FreeBSD and its derivatives, this contains just "user" entries. These entries are written by the same BSD C library routine that writes them to the table of active login sessions, and thus by the same programs at the same points. The table is not sorted nor sparse; rather, the BSD C library always searches for and overwrites any existing entry that has the same account name when writing to the table, appending new entries to grow the table by one record if it finds nothing to overwrite. (Login sessions for accounts with different names and the same user IDs will show up as separate entries in this table.) This makes it potentially slow to locate a specific account, which involves a table scan with account name comparisons, but fast to dump information on all accounts that have ever logged in.

On Linux operating systems this contains one record per system account and is indexed by account user ID. It is thus normally a very large but sparse file, with the empty never-written-to records for accounts that have never been logged into causing holes in the file. (Login sessions for accounts with different names and the same user IDs will supersede one another in this table, leaving just the latest one present.) This makes it fast to locate a specific account, the position of whose record can be directly indexed to, but slow to dump information on all accounts because it has to skip a lot of empty records.

The commands

On both sets of platforms, the who and the w commands (by default) read from the active login sessions table; and the last command reads from the log of login events. On FreeBSD and its derivatives, the lastlogin comand reads from the table of account statuses. On Linux operating systems, it is the lastlog command that reads from the table of account statuses.

On both sets of platforms, the "boot" entry for the current bootstrap can be found in both the active login sessions table and the log of login events, and so can be listed with either who -b or (since it always has an account name of "reboot") last reboot.

On FreeBSD and its derivatives, the "shutdown" entry for the preceding bootstrap can be found in the log of login events, and so can be listed with (since it always has an account name of "reboot") last reboot. On Linux operating systems, there is no "shutdown" entry type, but the log of login events does include "runlevel" events, of which system shutdown is considered to be one, that can be listed with who -r.

Further reading


© Copyright 2018 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.