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.
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.


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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Reading fields from the text file. 4 101
delete query using perl dbi 3 108
Ned Perl Snippet to Read Files in Directory 5 74
Call Shell Script from Perl Script 6 133
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 …
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
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…

808 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