The typical UNIX® administrator has a key range of utilities, tricks, and systems he or she uses regularly to aid in the process of administration. There are key utilities, command-line chains, and scripts that are used to simplify different processes. Some of these tools come with the operating system, but a majority of the tricks come through years of experience and a desire to ease the system administrator's life. The focus of this series is on getting the most from the available tools across a range of different UNIX environments, including methods of simplifying administration in a heterogeneous environment.
Getting current user information
Getting a list of users currently using the UNIX system can be achieved in a
number of different ways. The most obvious and straightforward is to use the
who command. The who command
returns a list of users currently logged in, the terminal they are connected to,
the date they logged in and, if they are a remote user, the IP address of the
hostname that they logged in from.
You can see an example in Listing 1 below.
Listing 1. Using the
who command to return a list of users currently logged in
$ who
mc pts/2 Sep 12 14:29 (sulaco.mcslp.pri)
mcbrown pts/3 Sep 12 14:37 (nautilus.mcslp.pri)
|
On some systems, there is also a quicker format available using the
-q command-line option, as shown here in
Listing 2.
Listing 2. The
who command with the -q option
$ who -q
mc mcbrown
# users=2
|
This output is similar to another command available on some systems called users, which just outputs the list of users with no count (see Listing 3).
Listing 3. The
users command
$ users
mc mcbrown
|
You can often find out more detailed information by adding the
-a and -H command-line
options. The -a option includes all of the most recent
information from the /var/adm/utmpx file, which is used to record login
information. The same file also records other events, such as the date and time of
the boot and the last run level change. You'll be taking a closer look at the
information stored in that file later in this article. The
-H option adds header information to the columns of
output. You can see an example of this in Listing 4.
Listing 4. The
who command with the -a and -H options
$ who -aH
NAME LINE TIME IDLE PID COMMENTS
. system boot Sep 12 11:35
. run-level 3 Sep 12 11:35 3 0 S
zsmon . Sep 12 11:35 3:14 215
LOGIN console Sep 12 11:35 0:20 221
LOGIN console Sep 12 11:35 0:20 510 (:0)
mc + pts/2 Sep 12 14:29 . 569 (sulaco.mcslp.pri)
mcbrown + pts/3 Sep 12 14:37 0:12 675 (nautilus.mcslp.pri)
|
The first two lines give you the information about when the system was last booted and the date and details of the last run level change. The machine shown here is running Solaris, and it monitors the serial ports for logins using the zsmon daemon. Then you have two logins tagged to the console, one of these is the login for the active user, and the other is attached to an X Server (the :0 indicates the X Windows System screen reference).
The final two lines are remote logins using Secure Shell (SSH). For all active processes, you get a process ID, and that means you can identify the original user within the ps list by their ID.
The LINE column is the terminal the user is connected on; the console is obviously the main keyboard and monitor of the machine. The pts lines refer to pseudo-terminals created automatically to handle the remote SSH connections.
Of course, knowing who is on the local machine is interesting, but how about on other machines in your network?
Getting remote user information
There are two background services that provide remote user information,
rusers and rwho, which are
backed up by two daemons, rusersd (more commonly
referred to as in.rusersd) and
rwhod (also known as
in.rwhod). These both rely on the Remote Procedure Call
(RPC) protocol to share information across the network.
Traditionally, enabling rwhod and
rusersd was seen as a wasteful use of network
resources,
because these daemons broadcast information over the network continually, using up
bandwidth. On a network with a large number of hosts, the amount of information
generated can be considerable. Today, the quantity of information generated is
small in comparison to the speed of the network.
Neither rwhod or rusersd
are available on all systems but, for those that provide the tool, it can be an
easy way of getting the information you want. If the tools are not already
running, you need to start up the in.rwhod and
in.rusersd daemons.
Once the daemons are running, you have a number of tools available for outputting the information about all of the machines. The rwho tool is the remote and network-enabled version of the who tool. See Listing 5 for an example.
Listing 5. The rwho tool
$ rwho -a
mc solaris-desktop:console Sep 12 11:29 3:41
mc solaris-desktop:pts/1 Sep 12 11:32 :06
mc ultra3:pts/2 Sep 12 14:29
mcbrown ultra3:pts/3 Sep 12 14:37 :37
M |
The rwhod tool broadcasts information, and it captures the broadcast information from other hosts and collates it into the /var/spool/rwhod directory.
The rusers tool sends a broadcast over the network for the
rusersd daemon on the other hosts to return the
information about the users currently logged in, as seen here in
Listing 6.
Listing 6. The rusers tool
$ rusers
Sending broadcast for rusersd protocol version 3...
192.168.0.31 mc mcbrown
solaris-desktop. mc mc
|
Another tool available once the rwhod daemon is
running is ruptime, which returns the loading and uptime information for all
servers running rwhod in the local network.
Listing 7 shows an example. This makes a really great tool
for determining the status of your machines without having to log in to them
individually.
Listing 7. The ruptime tool
$ ruptime
solaris-desktop up 3:53, 1 user, load 0.00, 0.00, 0.00
ultra3 up 3:46, 2 users, load 0.00, 0.00, 0.00
|
For who and rwho, the
information about who that is currently connected to your
machine is recorded in the /var/adm/utmp file, and historical information about
users that have logged in (and logged out) is in the wtmp machine. Both of these
files contain a wealth of information, but the files are not available in an
immediate format. Let's take a closer look at these files and how you can display
that information.
Log files used for user activity
There are a number of files used to record user logins and activity. The three main files for recording this information are:
- utmp—This file records the information about users currently logged in. It should contain one record for each logged in user.
- wtmp—This file records all logins (and logouts) by users. On a busy system, this file is quite large, as it contains one login and one logout record. This file also contains some system-related log information, such as restart, shutdown, and date changes.
- lastlog—This file records the last login time for each user. This file contains only one record for each user.
Once you know how and when the files are written, the relationship between these files is quite straightforward. The basic sequence is as follows:
- When a user logs in, the lastlog file is opened, and their record with the login date and time is updated. Then the utmp is opened and their current login information is recorded. The login record (generally a copy of the information added to lastlog) is written to the utmp log to record the login information.
- During logout, the login record written to utmp is deleted (since the user is no longer logged in), but a new record is written to wtmp to record the fact that the user has logged out.
- The format of these files is entirely binary; there is no way to report the information without using a separate tool that reads and parses the information. In general, the basic format of the wtmp and lastlog files is the same, and they use a simple format to record the login time, the login line, and the hostname line information, as shown here in Listing 8, which shows the Solaris format.
Listing 8. Solaris format from wtmp
struct lastlog {
time_t ll_time;
char ll_line[UT_LINESIZE];
char ll_host[UT_HOSTSIZE];
};
|
The format is not the same on different operating systems, and you have to be careful to extract the right information. On AIX®, the utmp definition is shown in Listing 9.
Listing 9. utmp definition
struct utmp
{
char ut_user[8];
char ut_id[14]
char ut_line[12];
short ut_type;
pid_t ut_pid;
struct exit_status
{
short e_termination;
short e_exit;
}
|
Listing 10 shows the definition of the value of the ut_type field from the record.
Listing 10. Definition of the value of the ut_type field
#define EMPTY 0
#define RUN_LVL 1
#define BOOT_TIME 2
#define OLD_TIME 3
#define NEW_TIME 4
#define INIT_PROCESS 5
#define LOGIN_PROCESS 6
#define USER_PROCESS 7
#define DEAD_PROCESS 8
#define ACCOUNTING 9
#define UTMAXTYPE ACCOUNTING
|
The username information is not included in the record because it is encoded according to the users ID. If the ID of the user that logs in is 1000, then the lastlog record can be located by accessing the record written at 1000 x sizeof (struct lastlog).
The utmp file structure is similar but, because it is a sequential log of login and logout and other event entries, the record includes the login information in Listing 11.
Listing 11. utmp file structure definition
struct utmp {
char ut_line[UT_LINESIZE];
char ut_name[UT_NAMESIZE];
char ut_host[UT_HOSTSIZE];
time_t ut_time;
};
|
The Linux® ut_type has similar value definitions, as shown here in Listing 12.
Listing 12. Linux ut_type definition
#define UT_UNKNOWN 0
#define RUN_LVL 1
#define BOOT_TIME 2
#define NEW_TIME 3
#define OLD_TIME 4
#define INIT_PROCESS 5
#define LOGIN_PROCESS 6
#define USER_PROCESS 7
#define DEAD_PROCESS 8
#define ACCOUNTING 9
|
And a much more complex structure definition, as shown here in Listing 13.
Listing 13. More complex utmp structure definition
struct utmp {
short ut_type; /* type of login */
pid_t ut_pid; /* PID of login process */
char ut_line[UT_LINESIZE]; /* device name of tty - "/dev/" */
char ut_id[4]; /* init id or abbrev. ttyname */
char ut_user[UT_NAMESIZE]; /* user name */
char ut_host[UT_HOSTSIZE]; /* hostname for remote login */
struct exit_status ut_exit; /* The exit status of a process
marked as DEAD_PROCESS */
/* The ut_session and ut_tv fields must be the same size when
compiled 32- and 64-bit. This allows data files and shared
memory to be shared between 32- and 64-bit applications */
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
int32_t ut_session; /* Session ID, used for windowing */
struct {
int32_t tv_sec; /* Seconds */
int32_t tv_usec; /* Microseconds */
} ut_tv; /* Time entry was made */
#else
long int ut_session; /* Session ID, used for windowing */
struct timeval ut_tv; /* Time entry was made */
#endif
int32_t ut_addr_v6[4]; /* IP address of remote host */
char __unused[20]; /* Reserved for future use */
};
|
Most systems come with simple tools to extract the information for you. To dump
out the contents of the wtmp file, use the last
command. This simply dumps out all the information (see
Listing 14).
Listing 14. Dumping out the contents of the wtmp file using the
last command
$ last
statmon ftp nautilus.mcslp.p Wed Sep 12 15:50 - 15:50 (00:00)
statmon ftp narcissus.mcslp. Wed Sep 12 15:50 - 15:50 (00:00)
statmon ftp nostromo.mcslp.p Wed Sep 12 15:50 - 15:50 (00:00)
statmon ftp sulaco.mcslp.pri Wed Sep 12 15:49 - 15:49 (00:00)
statmon ftp nautilus.mcslp.p Wed Sep 12 15:45 - 15:45 (00:00)
statmon ftp nostromo.mcslp.p Wed Sep 12 15:45 - 15:45 (00:00)
statmon ftp narcissus.mcslp. Wed Sep 12 15:45 - 15:45 (00:00)
|
You can often filter the information by user, host, or tty if you need to. For example, to get all of the logins by root, use what is shown in Listing 15.
Listing 15. Getting all logins by root
$ last root
root console :0 Mon Sep 25 11:32 - 11:32 (00:00)
root console :0 Mon Sep 25 11:27 - 11:27 (00:00)
root console Sat Sep 9 13:17 - 13:28 (00:11)
root console Sat Sep 9 10:47 - 13:14 (02:26)
root console Sun Sep 3 06:52 - down (6+03:54)
root console :0 Sat Sep 2 14:24 - down (16:27)
root console Sat Sep 2 08:02 - down (06:13)
root console Fri Aug 25 17:16 - down (00:39)
root console Sun Aug 20 16:04 - 16:04 (00:00)
root console Thu Jul 20 07:23 - 07:31 (00:07)
root console Thu Jul 20 07:22 - 07:23 (00:00)
root console Thu Jul 20 02:57 - 02:57 (00:00)
root console Wed Jul 19 12:22 - down (05:38)
root console Wed Jul 19 12:10 - 12:19 (00:08)
root console :0 Wed Jul 19 12:05 - 12:09 (00:04)
root console Wed Jul 19 11:47 - 11:55 (00:07)
wtmp begins Wed Jul 19 09:54
|
Because the wtmp also contains information about reboots and shutdowns, you can list that information, too (see Listing 16).
Listing 16. Getting information about reboots and shutdowns
$ last reboot
reboot system boot Wed Sep 12 11:28
reboot system down Wed Sep 5 12:16
reboot system boot Mon Sep 3 13:03
reboot system down Thu Mar 1 11:33
reboot system boot Thu Mar 1 09:57
reboot system down Thu Mar 1 08:12
reboot system boot Thu Mar 1 08:05
reboot system down Thu Mar 1 08:12
reboot system boot Thu Mar 1 08:05
reboot system down Thu Mar 1 08:03
reboot system boot Thu Mar 1 08:02
reboot system down Sun Dec 17 10:04
reboot system boot Sun Dec 17 10:02
reboot system down Mon Sep 25 11:44
reboot system boot Mon Sep 25 10:2
|
The previous tools are fine, but what if you want to parse the information
yourself? You could write a simple C program to extract the information but, in
fact, you can also do it with Perl by using the
unpack() function.
Using the unpack function within Perl requires
creating a suitable packstring, which defines the datatypes that you are going to
extract from the binary record data that you actually read from the raw binary
utmp file.
Listing 17 shows a very simple Perl script that does a direct dump of the data in wtmp.
Listing 17. Perl script that dumps the data in wtmp
my $packstring = "a8a8a8ssssl";
my $reclength = length(pack($packstring));
my @ut_types = qw(EMPTY RUN_LVL BOOT_TIME OLD_TIME
NEW_TIME INIT_PROCESS LOGIN_PROCESS
USER_PROCESS DEAD_PROCESS ACCOUNTING);
open(D,"</var/log/wtmp") or die "Couldn't open wtmp, $!";
while(sysread(D,my $rec,$reclength))
{
my ($user,$userid,$line,$pid,$type,$eterm,$eexit,$time)
= unpack($packstring,$rec);
print("$user, $userid, $line, $pid, $ut_types[$type], ",
"$eterm, $eexit, ", scalar localtime($time),"\n");
}
close(D) or die "Couldn't close wtmp, $!";
|
Note that you have to read the data using sysread because you are reading raw binary packets (not lines). The packstring you use gets the username, userid, ttyline, PID, utmp type, terminal exit code, and time.
The first three fields are the important ones, as they contain the line, name, and host information. The size of these fields is conveniently defined in utmp.h (see Listing 18).
Listing 18. Size of the first three fields defined in utmp.h
#define UT_NAMESIZE 8
#define UT_LINESIZE 8
#define UT_HOSTSIZE 16
|
Note that you must get the size right, as it affects the information you read. If you have a Solaris or BSD system, it uses the simpler structure that was shown in Listing 8, so you need a different packstring and extracted fields, as shown here in Listing 19.
Listing 19. Data dump with Solaris or BSD system
my $packstring = "a8a8a16l";
my $reclength = length(pack($packstring));
my @ut_types = qw(EMPTY RUN_LVL BOOT_TIME OLD_TIME
NEW_TIME INIT_PROCESS LOGIN_PROCESS
USER_PROCESS DEAD_PROCESS ACCOUNTING);
open(D,"</var/log/wtmp") or die "Couldn't open wtmp, $!";
while(sysread(D,my $rec,$reclength))
{
my ($line,$name,$host,$time)
= unpack($packstring,$rec);
print("$line, $name, $host,", scalar localtime($time),"\n");
}
close(D) or die "Couldn't close wtmp, $!";
|
Running this script gives you the login information for wtmp. The lines where you get only the line information are logouts rather than logins, as shown here in this fragment in Listing 20.
Listing 20. Getting login information for wtmp
ftp599, statmon, nautilus.mcslp.p,Wed Sep 12 16:00:13 2007
ftp599, , ,Wed Sep 12 16:00:14 2007
ftp4003, statmon, sulaco.mcslp.pri,Wed Sep 12 16:04:35 2007
ftp4003, , ,Wed Sep 12 16:04:35 2007
ftp4035, statmon, narcissus.mcslp.,Wed Sep 12 16:05:00 2007
ftp4035, , ,Wed Sep 12 16:05:00 2007
ftp4037, statmon, nostromo.mcslp.p,Wed Sep 12 16:05:01 2007
ftp4037, , ,Wed Sep 12 16:05:02 2007
ftp4057, statmon, nautilus.mcslp.p,Wed Sep 12 16:05:14 2007
ftp4057, , ,Wed Sep 12 16:05:14 2007
|
In this article, you've taken a quick look at what happens when you log in, how the logins are recorded into the UNIX system, and how you can use that information to determine who is logged on currently and who has been logged on in the past. You could use a modified version of the Perl script, for example, to provide total user-time information and charge it back to a user or department.
Learn
-
System Administration Toolkit:
Check out other parts in this series.
-
System Administration Toolkit: Standardizing your UNIX command-line tools
(Martin Brown, developerWorks, May 2006): Read this article and learn how to use
the same command across multiple machines.
-
System Administration Toolkit: Time and event management
(Martin Brown, developerWorks, May 2006): The article covers the creation and
organization of time scripts using cron and at.
-
Scheduling recurring tasks in Java
(Tom White, developerWorks, November 2003): Read this article and earn how to
build a simple, general scheduling framework for task execution conforming to an
arbitrarily complex schedule.
-
Wikipedia pages on crontab:
Browse through additional information on contab.
-
The road to better programming: Chapter 11. Crontab management with cfperl
(Teodor Zlatanov, developerWorks, June 2003): Discover how crontab entries can be
added or deleted easily in series on developing a cfegine interpreter written in
Perl.
- For an article series that teaches you how to
program in bash, see:
- Bash by example, Part 1: Fundamental programming in the Bourne again shell (bash) (Daniel Robbins, developerWorks, March 2000)
- Bash by example, Part 2: More bash programming fundamentals (Daniel Robbins, developerWorks, April 2000)
- Bash by example, Part 3: Exploring the ebuild system (Daniel Robbins, developerWorks, May 2000).
-
Making
UNIX and Linux work together
(Martin Brown, developerWorks, April 2006): This article is a guide to getting
traditional UNIX distributions and Linux® working together.
-
IBM Redbooks:
Different systems use different tools, and the Solaris to Linux Migration: A
Guide for System Administrators helps you identify some key tools.
-
Exploring the Linux memory model
(Vikram Shukla, developerWorks, January 2006): This article helps you understand
how Linux uses memory, swap space and exchanges pages, and processes between the
two.
-
Popular content:
See what AIX and UNIX content your peers find interesting.
- Check out other articles and tutorials written
by Martin Brown:
-
AIX and
UNIX:
The AIX and UNIX developerWorks zone provides a wealth of information relating to
all aspects of AIX systems administration and expanding your UNIX skills.
-
New to AIX and UNIX?:
Visit the "New to AIX and UNIX" page to learn more about AIX and UNIX.
-
AIX Wiki:
A collaborative environment for technical information related to AIX.
- Search the AIX and UNIX library by topic:
- System administration
- Application development
- Performance
- Porting
- Security
- Tips
- Tools and utilities
- Java™ technology
- Linux
- Open source
-
Safari bookstore:
Visit this e-reference library to find specific technical resources.
-
developerWorks technical events and webcasts:
Stay current with developerWorks technical events and webcasts.
-
Podcasts: Tune in and
catch up with IBM technical experts.
Get products and technologies
-
IBM trial software:
Build your next development project with software for download directly from
developerWorks.
Discuss
- Participate in the
developerWorks blogs
and get involved in the developerWorks community.
- Participate in the AIX and UNIX forums:
- AIX —technical forum
- AIX 6 Open Beta
- AIX for Developers Forum
- Cluster Systems Management
- IBM Support Assistant
- Performance Tools—technical
- Virtualization—technical
- More AIX and UNIX forums
Martin Brown has been a professional writer for more than seven years. He is the author of numerous books and articles across a range of topics. His expertise spans myriad development languages and platforms—Perl, Python, Java™, JavaScript, Basic, Pascal, Modula-2, C, C++, Rebol, Gawk, Shellscript, Windows®, Solaris, Linux, BeOS, Mac OS X and more—as well as Web programming, systems management, and integration. He is a Subject Matter Expert (SME) for Microsoft® and regular contributor to ServerWatch.com, LinuxToday.com, and IBM developerWorks. He is also a regular blogger at Computerworld, The Apple Blog, and other sites. You can contact him through his Web site.
Comments (Undergoing maintenance)





