Last updated: 11 November 2026. Tested on Ubuntu 24.04 with OpenSSH 9.6p1. Sources are listed at the end.

When something looks wrong on a server, the first question is who logged in and from where. Linux keeps that answer in a few places, and each one records something different. This guide shows how to check login history on Linux with last, lastb, lastlog and the SSH auth log, using output from our own lab box, and points out the gap that catches most people: last does not show every SSH login.

Want key-only SSH on every server? The SSH Hardening Pack (₹99) has tested sshd_config drop-ins, an install script that checks your key login works before it reloads sshd, and a verify script.

The short answer

  • last lists interactive logins from /var/log/wtmp.
  • sudo lastb lists failed logins from /var/log/btmp.
  • lastlog shows each account’s most recent login.
  • The SSH auth log (/var/log/auth.log on Ubuntu and Debian, or journalctl -u ssh) is the only one of these that shows every SSH login, including key logins, scp, SFTP and one-off remote commands.
  • On Debian 13 and newer distributions, last, lastb and lastlog may be missing. Use wtmpdb last, lslogins --failed and lastlog2 there.

Our lab setup

We used an Ubuntu 24.04 machine with OpenSSH 9.6p1 and rsyslog, and two test users: deploy with a password and alice with an SSH key. Then we made a few logins on purpose:

  1. Wrong passwords for root, admin, oracle and deploy.
  2. A password login as deploy that ran one command and left (ssh deploy@server 'sleep 2').
  3. A key login as alice that also ran one command.
  4. An interactive password login as deploy with a terminal.

So the server saw three successful logins and four failed ones. Here is what each tool reported.

1. last: interactive logins

$ last -a
deploy   pts/1        Wed Nov 11 04:50    gone - no logout  127.0.0.1

wtmp begins Wed Nov 11 04:50:49 2026

One line, for the interactive session. The two logins that ran a command without a terminal, including Alice’s key login, are not there. last reads /var/log/wtmp, and sshd writes a wtmp record only when it gives the session a terminal (a pts/ device). File copies with scp, SFTP sessions and automation that runs ssh host command usually leave no trace in last.

Useful options: -a puts the source address in the last column, -i shows IP addresses instead of host names, -F prints full start and end times, and -n 20 limits the output. last reboot lists reboots from the same file.

“gone – no logout” means wtmp has no matching logout record. In our lab that came from the test setup. On a real server it shows up after a crash, a killed session, or a session that is still open.

2. lastb: failed logins

$ sudo lastb -a
deploy   ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1
oracle   ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1
oracle   ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1
admin    ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1
admin    ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1
root     ssh:notty    Wed Nov 11 04:50 - 04:50  (00:00)     127.0.0.1

lastb needs root because /var/log/btmp holds the usernames people typed, and sometimes a password typed into the username field. Notice that admin and oracle appear twice. Neither account exists on the box, and sshd wrote one record when it rejected the unknown user and another for the failed password. So count source addresses and time windows, not lines.

To see which addresses try hardest:

sudo lastb -i | awk '$3 ~ /^[0-9a-f.:]+$/ {print $3}' | sort | uniq -c | sort -rn | head

The awk filter skips the “btmp begins” line at the end. In our lab it printed 6 127.0.0.1. A long list of failures from many addresses is normal for any server with SSH open to the internet. What matters is whether a success follows. Our fail2ban guide shows how to block the noisy addresses automatically.

3. lastlog: the last login of every account

$ lastlog -u deploy
Username         Port     From          Latest
deploy           pts/1    127.0.0.1     Wed Nov 11 04:50:49 +0000 2026

Run lastlog without options and it lists every account, mostly with “Never logged in”. Hide those to see the accounts that matter:

lastlog | grep -v 'Never logged in'

This is a quick way to spot a service account such as www-data, postgres or backup that has logged in when it never should. In our lab, alice stayed at “Never logged in” even though her key login succeeded, because it had no terminal. So lastlog has the same blind spot as last.

4. The SSH auth log: every login

$ grep -E 'Accepted|Failed password|Invalid user' /var/log/auth.log
... sshd[1037]: Failed password for root from 127.0.0.1 port 38062 ssh2
... sshd[1041]: Invalid user admin from 127.0.0.1 port 38078
... sshd[1041]: Failed password for invalid user admin from 127.0.0.1 port 38078 ssh2
... sshd[1045]: Invalid user oracle from 127.0.0.1 port 38088
... sshd[1045]: Failed password for invalid user oracle from 127.0.0.1 port 38088 ssh2
... sshd[1049]: Failed password for deploy from 127.0.0.1 port 51438 ssh2
... sshd[1054]: Accepted password for deploy from 127.0.0.1 port 51450 ssh2
... sshd[1068]: Accepted publickey for alice from 127.0.0.1 port 51454 ssh2: ED25519 SHA256:nVRzq7DN...
... sshd[1083]: Accepted password for deploy from 127.0.0.1 port 51466 ssh2

All three successful logins are here, with the method. “Accepted publickey” also prints the fingerprint of the key that was used, so you can tell which of several keys in authorized_keys logged in. Match it against the keys on the server with:

ssh-keygen -lf ~alice/.ssh/authorized_keys

To list only successful logins:

sudo grep 'Accepted ' /var/log/auth.log

Older entries are in rotated files. zgrep reads the compressed ones too:

sudo zgrep -h 'Accepted ' /var/log/auth.log*

On RHEL, Rocky and AlmaLinux the file is /var/log/secure. On systems that only keep the systemd journal, ask journald instead. The SSH unit is called ssh on Ubuntu and Debian and sshd on most other distributions:

sudo journalctl -u ssh --since "2 days ago" | grep -E 'Accepted|Failed'

Anything that says “Accepted password” for an account that should only use keys, or a login from an address you don’t recognise, is worth chasing. So is a successful login right after a burst of failures from the same address.

5. who and w: who is on right now

who lists users with an open terminal session, and w adds what each one is running and how long they have been idle. Both read /run/utmp, so they have the same blind spot as last. Our lab container had no /run/utmp at all and who printed nothing while two people were logged in, which is common in containers and minimal images. The sshd processes are a better check, because sshd starts one for every session:

$ ps -ef | grep -E '[s]shd: .+@'
alice     1148  1136  0 04:53 ?   00:00:00 sshd: alice@notty
deploy    1158  1135  0 04:53 ?   00:00:00 sshd: deploy@pts/1

@pts/1 is a terminal session and @notty is a key login running a command, the kind who and last never show.

6. Debian 13 and newer: wtmpdb and lastlog2

The old wtmp, btmp and lastlog files store login times in a way that stops working in 2038. Debian 13 (trixie) therefore no longer ships last, lastb or lastlog. According to its release notes, the replacements are:

Old commandReplacement on Debian 13Package
lastwtmpdb lastwtmpdb (plus libpam-wtmpdb)
lastloglastlog2lastlog2 (plus libpam-lastlog2)
lastblslogins --failedutil-linux

The release notes also say no tool reads the old /var/log/lastlog and /var/log/btmp files after the upgrade. If you are investigating an older incident on an upgraded server, copy those files before anyone cleans them up. Other distributions are moving the same way, so check which commands your servers have before you need them in a hurry. The SSH auth log works the same everywhere.

A five-minute login review

Put together, a quick review after a scare looks like this:

sudo grep 'Accepted ' /var/log/auth.log            # every successful SSH login
last -a -i -n 30                                  # recent interactive sessions
sudo lastb -i | awk '$3 ~ /^[0-9a-f.:]+$/ {print $3}' | sort | uniq -c | sort -rn | head   # who keeps trying
lastlog | grep -v 'Never logged in'               # accounts that have ever logged in
ps -ef | grep -E '[s]shd: .+@'                    # who is connected now

If you find a login you can’t explain, don’t log out of your own session and don’t clean anything yet. Copy the logs off the server, check authorized_keys files and recently added users, and treat the host as compromised until you know otherwise. In India, unauthorised access to IT systems has to be reported to CERT-In within six hours of noticing it under the CERT-In Directions of 28 April 2022.

Key-only logins make this review much shorter, because a password login then stands out at once. Our SSH hardening checklist shows the tested settings.

Related guides

Sources

Not sure who has access to your servers? Book our Linux server hardening and security audit and we will review your SSH setup, users and logs, or run the free website safety check for the web side. Contact us for a quote.

Post author avatar

Bhaskar Soni

Bhaskar Soni is a Security Engineer and the founder of Youngster Company, based in Ahmedabad, Gujarat. He works hands-on with Linux server hardening, vulnerability assessment and penetration testing (VAPT), ISO 27001 compliance and OSINT investigations. He writes practical, tested guides for IT professionals and Indian businesses, and every article on this site is written or reviewed by him.

Leave a Reply