Checking last logins with lastlog

keyboard adikos
Credit: flickr / adikos

How would you like an easy way to determine the last login date for everyone on your system and prepare a list of those accounts that have never logged in at all? If you don’t know the lastlog command, you might be delighted with how easily it can provide this kind of information.

When you think about it, one of the many useful security checks that you can perform on your Linux systems is to determine the last login dates for each of your users. This kind of check can help you to detect potential problems. Accounts that haven’t been used in a very long time, for example, might indicate that those accounts are no longer needed and should be locked; maybe those individuals have changed their job assignments and you weren’t notified. Accounts that are logged into in the middle of the night or when their legitimate users are on a cruise to the Bahamas might indicate another sort of problem altogether.

The last command will show you recent logins on your system but will only show you logins that are recorded in your active wtmp file. And it displays these logins with the most recent shown first, though you can also use commands like “last madman1” to show the logins for one individual.

$ last | head -4
shs     pts/6  Sun Apr 26 12:38   still logged in
madman1 pts/3   Sun Apr 26 12:00   still logged in
madman1 pts/10   Sat Apr 25 16:13 - 22:12  (05:58)
shs     pts/7  Sat Apr 25 15:35 - 16:27  (00:52)

How far back you can look with the last command will depend on how long you maintain your wtmp files and whether you maintain more than one generation. For example, you can use the logrotate utility to maintain more than one wtmp file with a logrotate.conf entry like this:

# keep one older wtmp file
/var/log/wtmp {
    minsize 1M
    create 0664 root utmp
    rotate 1

Even with multiple wtmp files, however, some of your users might just not appear in the output at all. If you get a response like this when checking on a particular individual, all you will know is that they haven’t logged in during the lifetime of your wtmp files.

$ last mia

wtmp begins Mon Feb 16 10:50:54 2015

The best way to find the last login for each individual is to use the lastlog command. This command will extract data from the lastlog file (/var/log/lastlog) and display the last login recorded for everyone with an account on your server. If any of your users have never logged in, it will indicate that as well. The output will look something like this:

$ lastlog | more
Username    Port     From             Latest
root        pts/0  Tue Jul 22 21:56:07 -0400 2014
bin                                   **Never logged in**
daemon                                **Never logged in**
adm                                   **Never logged in**
lp                                    **Never logged in**
shs         pts/6    Sun Apr 26 12:38:53 -0400 2015
mia         pts/1     Mon Dec 17 11:15:07 -0500 2012

None of us will likely be very surprised to see that bin, daemon, adm, lp, and other service accounts have never logged in. It’s likely, in fact, that the login shells for these accounts are set to /sbin/nologin to make logins impossible. The other entries, on the other hand, show the login dates and times along with the system where the login came from. Clearly, the user “mia” hasn’t logged in since late 2012.

To generate a list of all the accounts that have never been logged into, use a command like this:

$ lastlog | grep Never | awk '{print $1}'

The records in the lastlog command output are listed in UID order – from root to the user with the highest UID in your /etc/passwd file. This is due to the format of the lastlog (/var/log/lastlog) file itself. Unlike most Unix log files, the lastlog file has a dedicated space for each user’s login record and the location of each record is indexed by the UID. These files will then tend to be of a fixed size, especially if your system has an account at the upper limit of your possible UID range – such as UID 65535 (16 bit UID field maximum) and lots of unused space (unless your UIDs are strictly sequential). If the system you’re managing uses 32 bit UIDs, the file can be very large, allowing for 4,294,967,296 (2^32) records. Since some systems will set the nfsnobody account a UID of 4294967295 rather than 65534, this could be very noticeable.

Each record in the lastlog file contains the date and time of the most recent login, followed by the pseudo-terminal associated with that login and the identity of the system that the user logged in from. The record for root (UID 0) at the top of the file might look like this:

$ od -xc /var/log/lastlog | more
0000000 1637 53cf 7470 2f73 0030 0000 0000 0000
        7 026 317   S   p   t   s   /   0  \0  \0  \0  \0  \0  \0  \0
0000020 0000 0000 0000 0000 0000 0000 0000 0000
       \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000040 0000 0000 6f62 6f73 2e6e 6170 7472 2e73 
       \0  \0  \0  \0   b   o   s   o   n   .   p   a   r   t   s   .
0000060 726f 0a67 0000 0000 0000 0000 0000 0000
        o   r   g  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000100 0000 0000 0000 0000 0000 0000 0000 0000
       \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0

Because of the format of the lastlog file, it is not a file that lends itself to truncation or rotation. Think fixed size (unless your max UID is increasing) and no need for earlier information since we’re only saving the most recent login data. So, never even think of truncating or rotating this file. Also, it falls into a class of files called “sparse files” – a special type of file that uses space more efficiently when large sections of it are basically “empty” space. The size shown when you do a long listing may be considerably larger than the space the file actually occupies on your disk on systems which support this feature. You can use a command like this to see whether your lastlog file is sparse. Notice that the size on the left (1.3M) is smaller than the reported size of 1642500 bytes.

$ ls -alsh /var/log/lastlog
1.3M -rw-r--r-- 1 root root 1.6M Apr 26 22:22 /var/log/lastlog

Notice that the size shown on the left (1.3M) is smaller than the one the ls –l normally displays (1.6M).

The lastlog command can be very useful when you're checking on the logins that you support and making sure that the accounts on the system you manage are used properly and are still legitimate.  Make sure to verify the size if it appears much larger than makes sense on your system.

This story, "Checking last logins with lastlog" was originally published by ITworld.