ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


FreeBSD Basics

Monitoring Unix Logins

02/14/2001

Also in FreeBSD Basics:

Fun with Xorg

Sharing Internet Connections

Building a Desktop Firewall

Using DesktopBSD

Using PC-BSD

In today's article, I'd like to take a look at utmp, wtmp, and lastlog. These three files are read and updated whenever a user logs in to your FreeBSD system. However, you can't read these files directly, so we'll also look at the various utilities you can use to garner the information contained within these files. We'll then finish off the article with some utilities that deal with logins and terminals.

Let's start with /var/log/lastlog. When a user logs in, the login utility reads this file to determine the last time that user logged in to your FreeBSD system; it will then make a new entry in this file to indicate the time of the new login. Let's see what happens when the user "genisis" logs into my FreeBSD system:

login: genisis
Password:
Warning: your password expires on Tue Feb 6 14:50:29 2001
Last login: Sat Feb 3 15:56:53 from biko
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
The Regents of the University of California. All rights reserved.

Welcome to FreeBSD 4.2!!!
You have new mail.

You cannot kill time without injuring eternity.

Let's see what happened here. The login utility accepted the password for genisis and compared it to the encrypted hash stored in /etc/master.passwd. It also read /etc/login.conf to determine that the password was long enough, as we had previously set a minimum password length in Establishing Good Password Policies, and noticed that this user's password will expire on Tuesday. It then read /var/log/lastlog to determine the last time this user had logged in (it looks like the last login occurred on Saturday from a computer named "biko"), and then displayed the copyright notice, my customized message of the day, an alert that mail was waiting, and a nice fortune cookie courtesy of Henry David Thoreau before presenting the user with a shell prompt.

It is possible to bypass these messages at login time. As the user genisis, I'll create an empty file called .hushlogin in my home directory:

cd
touch .hushlogin

I'll then logout and log back in again:

exit

login: genisis
Password:

Alimony is a system by which, when two people make a mistake, one of them keeps paying for it.
-- Peggy Joyce

Notice that the only thing the user genisis received this time was the fortune cookie. Remember, that fortune cookies are invoked by the shell's configuration file, so it came courtesy of the user's shell. (see Customizing the Login Shell) However, this login may be a bit too quiet as the user won't receive the message regarding the pending password change or any messages the administrator may have included in the message of the day.

The second login record file is /var/run/utmp. This file contains information regarding users that are currently logged in and is read by the w, who, and users commands. Let's take a closer look at each of these utilities, starting with users:

users
genisis test1 test2 test3

The users command is useful if you just need to know which users are logged in and don't want to sort through all the details of where they are logged in and what they are doing. However, if you need to know who is logged into which terminals, use the w command:

w

5:01PM up 3:30, 7 users, load averages: 0.04, 0.06, 0.02
USER TTY FROM LOGIN@ IDLE WHAT
genisis v0 - 1:31PM 1 more
genisis v1 - 1:32PM - w
genisis v2 - 1:32PM 3:11 xinit /home/genisis/.x
genisis v3 - 1:46PM - pico utmp
test3 v4 - 4:51PM - -tcsh (tcsh)
test1 p0 biko 4:50PM 10 -tcsh (tcsh)
test2 p1 biko 4:51PM 1 -tcsh (tcsh)

There are currently seven active logins on my FreeBSD system. The user genisis is physically sitting at my FreeBSD box and has logged into the first four virtual terminals (v0-v3). The user "test3" is also logged on locally using virtual terminal number 5 (v4). The user "test1" has logged into the first network terminal (p0) from a computer named "biko" and the user "test2" has logged into the second network terminal (p1) from the computer named "biko".

The IDLE column shows how long it has been since a user typed anything at a terminal, and the WHAT column shows what process is currently running on each terminal. To find out all the processes running on each terminal, use the d switch like so:

w -d |more

5:10PM up 3:39, 7 users, load averages: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE WHAT
219 -csh (csh)
1085 _su (csh)
1107 man w
1108 sh -c /usr/bin/zcat /usr/share/man/cat1/w.1.gz | more
1110 more
genisis v0 - 1:31PM 10 more
220 -csh (csh)
1138 w -d
genisis v1 - 1:32PM - w -d
221 -csh (csh)
396 /bin/sh /usr/X11R6/bin/startx
401 xinit /home/genisis/.xinitrc --
403 xfce
408 /usr/local/lib/netscape-linux/navigator-linux-4.76.bin
409 (dns helper) (navigator-linux-)
genisis v2 - 1:32PM 3:20 xinit /home/genisis/.x
222 -csh (csh)
977 pico utmp
genisis v3 - 1:46PM - pico utmp
1074 -tcsh (tcsh)
test3 v4 - 4:51PM 9 -tcsh (tcsh)
1061 -tcsh (tcsh)
test1 p0 biko 4:50PM 19 -tcsh (tcsh)
1066 -tcsh (tcsh)
test2 p1 biko 4:51PM 7 -tcsh (tcsh)

I ran this command as a regular user; you don't have to be the superuser to know what is running on all of the terminals on your FreeBSD system. However, regular users will only be able to manipulate their own processes.

The who command gives output similar to the w command as it shows the user's login name, terminal name, time of login, and which computer the user logged in from.

who

genisis    ttyv0   Feb  3 13:31
genisis    ttyv1   Feb  3 13:32
genisis    ttyv2   Feb  3 13:32
genisis    ttyv3   Feb  3 13:46
test3      ttyv4   Feb  3 16:51
test1      ttyp0   Feb  3 16:50    (biko)
test2      ttyp1   Feb  3 16:51    (biko)

You'll receive different results if you run the who command with the am i option:

who am i
genisis    ttyv1   Feb  13:32

It looks like genisis ran the above command at the second virtual terminal.

You can also tell the who command to read the /var/log/wtmp file instead of the default /var/run/utmp file:

who /var/log/wtmp

genisis     ttyv0   Feb  3 13:25
shutdown    ~       Feb  3 13:30
            ttyv0   Feb  3 13:30
reboot      ~       Feb  3 13:31
genisis     ttyv0   Feb  3 13:31
genisis     ttyv1   Feb  3 13:32
genisis     ttyv2   Feb  3 13:32
genisis     ttyp0   Feb  3 13:34   (biko)
genisis     ttyv3   Feb  3 13:46
genisis     ttyp1   Feb  3 15:04   (biko)
genisis     ttyv4   Feb  3 15:04
            ttyp0   Feb  3 15:31
genisis     ttyp0   Feb  3 15:56   (biko)
            ttyp0   Feb  3 16:00
genisis     ttyp0   Feb  3 16:00   (biko)
            ttyp0   Feb  3 16:23
genisis     ttyp0   Feb  3 16:23   (biko)
            ttyp0   Feb  3 16:23
genisis     ttyp0   Feb  3 16:23   (biko)
            ttyv4   Feb  3 16:32
genisis     ttyv4   Feb  3 16:32
            ttyv4   Feb  3 16:32
genisis     ttyv4   Feb  3 16:32
            ttyp0   Feb  3 16:45
            ttyp1   Feb  3 16:45
test1       ttyp0   Feb  3 16:50   (biko)
test2       ttyp1   Feb  3 16:51   (biko)
            ttyv4   Feb  3 16:51
test3       ttyv4   Feb  3 16:51
            ttyv4   Feb  3 17:36
shutdown    ~       Feb  3 20:39
            ttyv3   Feb  3 20:39
            ttyv1   Feb  3 20:39
            ttyv0   Feb  3 20:39
            ttyv2   Feb  3 20:39
reboot      ~       Feb  3 20:40
genisis     ttyv0   Feb  3 20:40
genisis     ttyv1   Feb  3 20:40
genisis     ttyv2   Feb  3 20:40
genisis     ttyv3   Feb  3 20:43
genisis     ttyv4   Feb  4 08:25

Notice that this output also contains the times of reboots and shutdowns. On your system, the output may have been much longer, depending on how often users log in and out of your FreeBSD system. If your output is too long, you can view just the last 10 entries with the following command:

who /var/log/wtmp | tail

The file /var/log/wtmp makes a record for every login, logout, date change, shutdown, and reboot. You can also access the information in the /var/log/wtmp file by using the last and ac commands. Let's compare the above output to the output of the last command:

last
genisis ttyv4 Sun Feb 4 08:25 still logged in
genisis ttyv3 Sat Feb 3 20:43 still logged in
genisis ttyv2 Sat Feb 3 20:40 still logged in
genisis ttyv1 Sat Feb 3 20:40 still logged in
genisis ttyv0 Sat Feb 3 20:40 still logged in
reboot ~ Sat Feb 3 20:40
shutdown ~ Sat Feb 3 20:39
test3 ttyv4 Sat Feb 3 16:51 - 17:36 (00:44)
test2 ttyp1 biko Sat Feb 3 16:51 - shutdown (03:48)
test1 ttyp0 biko Sat Feb 3 16:50 - shutdown (03:48)
genisis ttyv4 Sat Feb 3 16:32 - 16:51 (00:18)
genisis ttyv4 Sat Feb 3 16:32 - 16:32 (00:00)
genisis ttyp0 biko Sat Feb 3 16:23 - 16:45 (00:21)
genisis ttyp0 biko Sat Feb 3 16:23 - 16:23 (00:00)
genisis ttyp0 biko Sat Feb 3 16:00 - 16:23 (00:22)
genisis ttyp0 biko Sat Feb 3 15:56 - 16:00 (00:03)
genisis ttyv4 Sat Feb 3 15:04 - 16:32 (01:27)
genisis ttyp1 biko Sat Feb 3 15:04 - 16:45 (01:41)
genisis ttyv3 Sat Feb 3 13:46 - shutdown (06:52)
genisis ttyp0 biko Sat Feb 3 13:34 - 15:31 (01:57)
genisis ttyv2 Sat Feb 3 13:32 - shutdown (07:06)
genisis ttyv1 Sat Feb 3 13:32 - shutdown (07:06)
genisis ttyv0 Sat Feb 3 13:31 - shutdown (07:07)
reboot ~ Sat Feb 3 13:31
shutdown ~ Sat Feb 3 13:30
genisis ttyv0 Sat Feb 3 13:25 - shutdown (00:04)
reboot ~ Sat Feb 3 13:25
wtmp begins Sat Feb 3 13:25:04 2001

You'll notice that the entries are in reverse order, so you see the most recent events first. This means that if you want to limit the output to 10 lines, you should pipe it to the head command as you wish to see the head-end of the file rather than the tail-end. That is, to only see the 10 most recent entries, type:

last | head

The last three columns are interesting as they show what time the user logged in, what time they logged out, and the duration of the login session. It also makes note if the user was forcibly logged out due to a shutdown or reboot.

The last command also supports several switches; a useful switch is the word reboot:

last reboot
reboot       ~          Sat Feb  3 20:40 
reboot       ~          Sat Feb  3 13:31 
reboot       ~          Sat Feb  3 13:25 
wtmp begins Sat Feb  3 13:25:04 2001

This will give a nice summary of the times and dates your FreeBSD system rebooted.

The ac utility adds up the connection times that are recorded in /var/log/wtmp and can be used to get a rough idea of which users are using the most connection time. If you run ac without any switches, you'll be given a number that represents a total of all connection times contained within /var/log/wtmp:

ac
	total	165.04

To see the total number of connection hours on a daily basis:

ac -d
Feb  3  total      124.42
Feb  4  total       41.52

And to see the total hours for each user for the entire period of the /var/log/wtmp file:

ac -p
	test1           4.12
	test2           4.11
	test3           0.75
	genisis       156.06
	total         165.04

To summarize: The utilities w, who, and users display information contained in the file /var/run/utmp; the utilities last and ac display the information contained in /var/log/wtmp.

The last thing I'd like to mention in today's article is locking unused terminals. Normally when a user finishes using a terminal, he or she will logout using either the exit or logout command. But sometimes a user needs to leave a terminal for a few minutes before finishing a session. It is good practice to lock your terminal if you need to be away from it, and your FreeBSD system comes with the lock utility for this purpose. If you just type lock, you'll be prompted for a "Key" or password to unlock the terminal:

lock
Key:
Again:
lock: /dev/ttyp0 biko timeout in 15 minutes
time now is Sun Feb  4 11:48:34 EST 2001
Key:

The terminal will now be locked for either 15 minutes or until the user returns and enters the key. If you don't want to be prompted to create a key when you invoke the lock utility, use lock -p; your key will be your login password. If you want to lock a terminal for more than 15 minutes, use lock -n. The only way to bypass a locked terminal is to know the key, wait for the timeout period, or to have the superuser send a kill signal to the PID of the lock process from a different terminal.

There is also a utility called vlock that you can build using the ports collection. As the superuser and while connected to the Internet:

cd /usr/ports/security/vlock
make install clean

Once the port has been installed, you can leave the superuser account. To use vlock:

vlock
This TTY is now locked.
Please enter the password to unlock.
genisis's Password:

You'll note that this utility only uses the user's password as the key and that the terminal will be locked until a password is entered. However, the superuser can unlock this terminal directly by entering root and then the password for the root account:

genisis's Password: (type in the word "root")
root's Password:

The vlock utility can also lock all the virtual terminals on a FreeBSD system without affecting network logins. If I type vlock -a, my screen will look like this:

The entire console display is now completely locked.
You will not be able to switch to another virtual console.
Please enter the password to unlock.
genisis's password

At this point, my ALT Function keys no longer work and the machine is unavailable for users who physically walk up to my FreeBSD machine unless they happen to know the password for the user "genisis" or the root account. This feature is handy if your FreeBSD box is acting as a server as it will still accept network logins.

In next week's article, I'd like to shift gears a bit and talk about inodes.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.


Read more FreeBSD Basics columns.

Discuss this article in the Operating Systems Forum.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.