If who shows nobody logged in while a user is staring at a live X session, your display manager's sessreg hooks are probably broken. This guide gives you matching add and remove commands for an X display session, using the installed sessreg 1.1.3 from package x11-xserver-utils. It covers the utmpx and wtmpx records, the optional lastlog entry, and which older arguments no longer do anything at all.
Allow about fifteen minutes. You need an X display manager configuration that runs startup and reset hooks, the sessreg package, and permission to update the host's login-record files. Reading and checking the command is ordinary user work; installing the hook or writing system records normally needs an administrator account.
Confirm the command and package version match what this guide describes:
$ command -v sessreg
/usr/bin/sessreg
$ sessreg -V
sessreg 1.1.3
$ dpkg-query -W -f='${Package} ${Version}\n' x11-xserver-utils
x11-xserver-utils 7.7+10build2
The command takes one user name and requires exactly one of -a or -d: -a adds a session record, -d removes one. This build uses POSIX pututxline interfaces, so the old slot and mapping files play no part in its active operation.
Checkpoint: if sessreg -V reports a different release, read that machine's manpage before copying these examples. Small differences between login-record implementations matter.
For an X session, use the display name as the line name: commonly :0 for a local display, :1 for a second one. This value is metadata for the record, not a path to open. Use the account that actually owns the session, not the display manager's own account.
$ DISPLAY_NAME=':0'
$ SESSION_USER="$USER"
$ printf 'display=%s user=%s\n' "$DISPLAY_NAME" "$SESSION_USER"
display=:0 user=your-login
Replace :0 and your-login with values from your own hook; the display manager's documented environment is the better source for both. Quote your shell variables. A display name or account name should never be assembled by concatenating untrusted input into a larger shell command.
The normal add operation:
$ sudo sessreg -a -l "$DISPLAY_NAME" "$SESSION_USER"
$ printf 'sessreg add status: %s\n' "$?"
sessreg add status: 0
This uses the manpage's defaults: /var/run/utmp for the current-session record, /var/log/wtmp for history, and /var/log/lastlog where the platform supports it. Writing those files is why the example needs sudo. A zero exit status means the command completed; it does not print a summary of what it wrote.
For a remote X session, add -h HOSTNAME to identify the originating host:
$ sudo sessreg -a -l "$DISPLAY_NAME" -h 'workstation.example' "$SESSION_USER"
Leave -h out for an ordinary local display. Do not invent a host name here just to make the record look complete.
Checkpoint: inspect the result with a reader such as who or last, if available:
$ who
your-login :0 2026-09-26 09:41 (:0)
$ last -1 "$SESSION_USER"
your-login :0 :0 Sat Sep 26 09:41 still logged in
Formatting and which record sources a reader consults vary by system. The time, user and line displayed should match what you supplied. If the record is missing, check the command status, permissions and the reader's data source before repeating the add.
Pair the startup command with a reset command using the exact same user and line values:
$ sudo sessreg -d -l "$DISPLAY_NAME" "$SESSION_USER"
$ printf 'sessreg delete status: %s\n' "$?"
sessreg delete status: 0
Run this from the display manager's reset hook, after the X session has ended. The line name must match because the record identifies the session through it. If the startup hook used -h, use the same host value here when your deployment's hook needs the remote identity.
Recovery: this changes login accounting records, so do not experiment against live defaults with a guessed user name. If you remove the wrong session, the safe correction is to re-run the intended session's add hook with its exact identity, then verify the record. Never edit utmp or wtmp with a text editor.
When checking argument handling, disable all three record destinations explicitly. This is a good shell smoke test and does not need sudo:
$ sessreg -a -u none -w none -L none -l :99 demo-user
$ printf 'disabled-destination status: %s\n' "$?"
disabled-destination status: 0
The special value none disables writing to that destination; it is not a file called none. This checks option parsing and the add path, but it cannot prove a real utmpx or wtmpx entry got written. Use a disposable test host or the display manager's own maintenance procedure for genuine end-to-end accounting tests.
Warning: never replace /var/run/utmp, /var/log/wtmp or /var/log/lastlog with hand-created files. Their binary format and ownership are system interfaces. If you need alternate destinations for an integration test, use -u PATH, -w PATH and -L PATH only in an isolated environment where the platform's record implementation is known to support them.
Options -s, -t and -x are accepted by this build for compatibility but ignored. They refer to old slot-number, ttys-file and Xservers-file mappings. Do not waste time editing those files to fix a missing entry on this POSIX utmpx build. The options that actually matter are the destinations, line and host metadata, version, and the add or delete operation.
Old XDM-shaped examples often show -x /etc/X11/xdm/Xservers. It is harmless here as a compatibility argument but does not make sessreg consult that file. Keep it only when one shared hook must also satisfy an older implementation that genuinely needs it.
If the command fails, run sessreg -V and read man sessreg on that host first. Then check whether the target files exist, whether the hook runs as the account you expect, and whether a security policy blocks the write. Elevation can fix a file-permission problem, but it cannot turn an ignored compatibility option into an active one.
sessreg version and package.-a, the exact display line, and the real session user.-d with the same identity.