Last User Login Script

Posted on 1998-05-27
Last Modified: 2006-11-17
I am trying to write a script that will tell when a user on a network of 90 computers last logged in. Each Computer has its own wtmp file that holds last login information. The password file for the network is stored on a central computer and all the computers use NIS and NFS for file sharing. I want the script to go to each computer on the network (I have a list of computers it will read from called computer.list) and have it go in and tell me when the user last logged in on the network.
Question by:Enslaver

Expert Comment

ID: 1206417
You could certainly do this, but it would be wrong, from both efficiency and security standpoints.  Instead, let me suggest that you have each user run a perl script upon login (via the global login files, depending on shell).

That script will connect with a server running on some designated machine (make sure to set the name of the machine in an environment variable so that it can be easily changed later), and hand off the name of the user and the name of the machine being logged into to the server.

The server script, also, of course, written in perl, will simply store the current time, username and machine name.  You'll probably want to use a berkeley db file for this.

You'll  find an example server and client in the camel.


Author Comment

ID: 1206418
With a network of 1000+ users that would be too tough. And I am not concerned about security. I have already thought this through and found my way to be the best way to do it.
LVL 51

Expert Comment

ID: 1206419
can you finger your user at all hosts from computer.list?
Then it could be done.
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.


Author Comment

ID: 1206420
Nope, fingerd only accepts requests from localhost.
LVL 51

Expert Comment

ID: 1206421
Would be a hard job then ;-|

If fingerd is somehow secure, I assume that wtmp is not accesable from network too.

So you either must export your wtmp to a public (network-) accessable directory -not very clever-, or use a solution as b2pi suggested -you rejected-, or you do it similar as b2pi as follows:

each login writes to a public accessable file a notification line
a program reads this file at each login to get requiered information (you don't need a client/server solution for this)

Author Comment

ID: 1206422
Ok well my goal is to find out who to date hasnt logged in in 3 months. Not find out 3 months from now, and all wtmp's are accessable through nfs because we have each of the computers mounted on /net/computername

Accepted Solution

leendert earned 200 total points
ID: 1206423
Hi there,

Ok here is what I did. I wrote two perl programs. A client which
must be installed on the target computer and a "querylu" (Query
Last User) script that sits on your computer.

What you need to do is to install the client script on the target
computer and to create an entry in the /etc/services and
/etc/inetd files.

Here are two examples of such entries :

/etc/services file :
lastuser         5610/tcp

/etc/inetd.conf file :
lastuser    stream  tcp nowait  root /usr/lenny/bin/script/lastuser lastuser

Note : the above line must be on one line. it wrapped while I
typed it in. Modify the path to the script to suit your needs.

After you modified these files you will have to "kill -1" the
inetd process. So do a "ps -ef/-aux | grep inetd" and kill it
with a -1 (HUP) signal. This will force inetd to reload it's

The source of the lastuser script (client side) :


open (PWFile, "/etc/passwd");
@PWLines = <PWFile>;
close (PWFile);

foreach $PWLine (@PWLines) {
    chop ($PWLine);
    # Check for known user shells to identify valid users
    if ( ($PWLine =~ /ksh/) || ($PWLine =~ /tcsh/) ||
           ($PWLine =~ /csh/) || ($PWLine =~ /zsh/) ) {
        # This means we have a valid user.
        @Tok = split (/:/, $PWLine);
        $UserName = $Tok[0];
        $LastLine = `last | grep $UserName | head -1`;
        if ($LastLine ne "") {
            push (@LastLines, $LastLine);

while ($Input = <STDIN>) {
    if ($Input eq "all") {
        print @LastLines;
    else {
        foreach $Line (@LastLines) {
            if ($Line =~ /$Input/) {
                print $Line;
                `echo $Line > /tmp/dump`;

The source of the querylu (query last user ) script:


use Socket;

if ($#ARGV == -1) {
    printf ("Usage : querylu (all/<username>)\n");
$UserName = $ARGV[0];
open (CompFile, "computer.list") || die "Could not open computer.list file";
close (CompFile);
foreach $Computer (@CompLines) {
    chop ($Computer);

    $IAddr = inet_aton($Computer);
    $PAddr = sockaddr_in($QueryPort, $IAddr);
    $ProtoCol = getprotobyname('tcp');
    socket (SOCK, PF_INET, SOCK_STREAM, $ProtoCol) or die "Socket error : $!";
    connect (SOCK, $PAddr) or die "Connect error : $!";
    $| = 1;
    print SOCK "$UserName\n";
    while ( $Line  = <SOCK> ) {
        printf ("[$Computer]$Line");
    close (SOCK);

Notes :
You can modify the script to read the passwd file from your
central storage.

The query script will read the "computer.list"
file and query the specified users on the machines in the

If you decide to use a different port in the services file,
please modify it in the querylu script as well.

I use these scripts with Perl v 5.004_04 on freeBSD 2.2.6

Usage :

After these scripts are installed, you can query all the users
by typing : "querylu all"

or you can specify a username on the command line.

I hope this will help you. If you have more problems concerning
this, please let me know.


Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question