SSH-LAST(1)

πŸ’… ssh-last(1) β€” last, but make it SSH, bestie πŸ’…

okay so real talk: ssh-last is literally the icon we needed. It’s last but for SSH sessions, and it’s giving observability main character energy. Let’s get into it ✨

✨ NAME ✨

ssh-last β€” list last SSH sessions 🫢

🌸 SYNOPSIS 🌸

                     ssh-last [OPTIONS]
          ssh_logs | ssh-last [OPTIONS]

πŸŽ€ Options

  • -a β€” show all sessions (show data which is hidden by the 'ignored' file)
  • -c β€” colored output (highlight active SSH sessions)
  • -d β€” debug
  • -f β€” force showing fingerprints (no mapping from 'known' file)
  • -h β€” show this help message
  • -i β€” force showing certificate ids (no mapping from 'known' file, not together with -f)
  • -l β€” try to use logfiles instead of journalctl (may be even faster on some systems)
  • -n β€” show host/ip in cleartext (no mapping from 'known' file)
  • -w β€” show only active SSH sessions
  • -? β€” show complete manual with more detailed information (usually needs perl-doc installed to work properly)
  • --version β€” show version information

πŸ¦‹ Examples

ssh-last
ssh-last -c | more
ssh-last -c | less -R   # keeps colored output in less
ssh-last -cw

# Logs from yesterday
LC_TIME=C journalctl _COMM=sshd-session -g 'Accepted|Disconnected' --since yesterday               | ssh-last

# Logs from three days ago
LC_TIME=C journalctl _COMM=sshd-session -g 'Accepted|Disconnected' --since -3d --until -2d         | ssh-last

# Logs from the last hour
LC_TIME=C journalctl _COMM=sshd-session -g 'Accepted|Disconnected' --since -1h                     | ssh-last

# Logs until a specific date
LC_TIME=C journalctl _COMM=sshd-session -g 'Accepted|Disconnected' --until "2022-03-12 07:00:00"   | ssh-last

# From logfiles (order must be from oldest to newest)
zgrep -hE 'Accepted|Disconnected' auth.log.2.gz  auth.log.1  auth.log                      | ssh-last
zgrep -hE 'Accepted|Disconnected' $(ls /var/log/auth.log* --sort=time --reverse)           | ssh-last
zgrep -hE 'Accepted|Disconnected' $(ls /var/log/messages* --sort=time --reverse)           | ssh-last
zgrep -hE 'Accepted|Disconnected' $(ls /var/log/secure*   --sort=time --reverse)           | ssh-last

πŸ’œ DESCRIPTION πŸ’œ

ssh-last is like last but for SSH sessions. no cap, that’s the whole vibe πŸ’…

🌈 Output Flags

the AUTH_ID column is giving:

+--------------------------------------------------------------------------+
|                                                                          |
| AUTH_ID                                                                  |
|                                                                          |
| (C) sshd authorized login via (c)ertificate                              |
| (K) sshd authorized login via public (k)ey                               |
| (?) sshd authorized login via some other type (password, pam)            |
|                                                                          |
+--------------------------------------------------------------------------+

⭐ Algorithm

Milling through sshd logs in chronological order:

  1. Finding login (Accepted) and logout (Disconnected) lines.
  2. Storing info from the lines like username, auth_type, fingerprint, ...
  3. Using the used network port to check for active sessions and piecing together old sessions by remembering logged network ports
  4. Using mainly /etc/os-release to adapt for different systems which differ in logfile names, logging patterns, etc...

πŸŽ€ FILES πŸŽ€

πŸ™ˆ Ignored

  • /etc/ssh-tools/ssh-last/ignored
  • ~/.config/ssh-tools/ssh-last/ignored
  • ./ignored

These data will be hidden in output unless forced with -a option.

+--------------------------------------------------------------------------+
|# Fingerprints                                                            |
|                                                                          |
|SHA256:ElgyEn5xPe4VlK5jJkqauRdAKNRHdh2tGHfo0m9/IwW Jenkins                |
|SHA256:5xPe4JkqaElKNRHGHfxPe4RdAKdh2tlK5AKNRHn5xK5 foo          # comment |
|SHA256:nmKL5s7/fs45312nvjhFSRTREa44r2hfgJHJG54353R   bar@gmx.de           |
|                                                                          |
|# Hosts                                                                   |
|                                                                          |
|127.0.0.1       localhost   # local ssh logins                            |
|192.168.1.50    nas         # more comments                               |
|webserver                   # alias from the 'known' file                 |
|                                                                          |
|# Cert IDs                                                                |
|                                                                          |
|user1@company.com                                                         |
|user2@company.com with some info                                          |
|user3@company.com with some info # and a comment                          |
|                                                                          |
|# Users                                                                   |
|                                                                          |
|git # gitlab                                                              |
+--------------------------------------------------------------------------+

πŸ‘‘ Known

  • /etc/ssh-tools/ssh-last/known
  • ~/.config/ssh-tools/ssh-last/known
  • ./known

For these keys the mapped value will be shown instead of its key, unless forced with -f (fingerprints) and -n (hosts) or -i (certificate ids) option.

+--------------------------------------------------------------------------+
|# Fingerprints                                                            |
|                                                                          |
|SHA256:WwI/9m0ofHGt2hdHRNKAdRuaqkJj5KlV4ePx5nEyglE Sven Wick              |
|SHA256:xyk5ZZZWZKnmKL5mYdk8Poy5eds7/CD/JEwqykMnlQQ root@n40l    # comment |
|SHA256:G7h9i5+NDU72Ae40gCkxyvDz/8BH+KETw7sXHCYr5w0   sven.wick@gmx.de     |
|                                                                          |
|# Hosts                                                                   |
|                                                                          |
|127.0.0.1       localhost   # local ssh logins                            |
|192.168.1.50    nas         # more comments                               |
|192.168.50.100  webserver                                                 |
|                                                                          |
|# Cert IDs                                                                |
|                                                                          |
|user1@company.com   vaporup                                               |
+--------------------------------------------------------------------------+

πŸ’€ BUGS AND LIMITATIONS πŸ’€

🧚 JumpHosts

Using a JumpHost with ProxyCommand oder ProxyJump, may often result in an unclean disconnect with nothing logged, so LOGOUT and DURATION can not be displayed.

πŸ”₯ Unprivileged users

If possible, run ssh-last as root or via sudo.

  1. Logfiles and systemd's journal usually can't be read by a normal user
  2. ssh-last -w works only reliably as root, since ss and netstat do not show process info when invoked as normal user
  3. ssh-last tries to map the fingerprint from a user's authorized_keys file but users usually are not allowed to look into each others files

🌸 OS Upgrades

If you do an in-place upgrade like dist-upgrade on Debian/Ubuntu, depending on the version difference, it can happen that sshd logs differently from that point on and you may have a mix of logs in new and old format which results in ssh-last showing only the latest ones correctly.

πŸ“ Log inconsistency

I have seen cases where some sshd "Disconnect" log messages were missing in systemd's journal but existed in /var/log/auth.log. So, if ssh-last is not showing a logout and duration but the log lines exist in the logfile, check if the log message really reached systemd's journal since ssh-last defaults to journald.

πŸ¦‹ NOTES πŸ¦‹

πŸŽ€ Helper Scripts

For convenience you can create little wrapper scripts like the following which avoids parsing too many logs by limiting the data only to the last week:

my-ssh-last

#!/usr/bin/env bash

LC_TIME=C journalctl _COMM=sshd-session --since -1week \
| grep -E 'Accepted|Disconnected'              \
| ssh-last "$@"

🌈 SEE ALSO 🌈

ssh-keyinfo(1), ssh-certinfo(1)

πŸ’– AUTHOR πŸ’–

Sven Wick <sven.wick@gmx.de>


later bestie β€” source/version SSH-TOOLS, date 2026-10-26 πŸ’…βœ¨

πŸ“¦ where this page comes from