views:

3737

answers:

8

I have lots of home directories under /ifshome on Linux. I want to see which users have not logged in for the past 6 months, and my solution is to parse the /ifshome/user/.lastlogin file. Each .lastlogin file has the same format, 1 line:

Last Login: Fri Mar 09 18:06:27 PST 2001

I need to build a shell script that can parse the .lastlogin file in each user's home directory and output those directories whose owners haven't logged in for the last 6 months.

+1  A: 

Am I correct to assume that the latest time should more or less equal the change time of the file? If so, you can easily use the find command to find the files newer than six months ago.

Removing those files from the 'original' list would yield the older ones.

xtofl
A: 

Where does the .lastlogin file come from? Is that a linux standard, because I don't have one?

I just found the "lastlog" command on my system which can give you everyone who last logged in a specified number of days ago:

       -b, --before DAYS
           Print only lastlog records older than DAYS.

i wouldn't assume it's in the users home directory (would be pretty unsafe to rely on the user. they could easily change the file). so that wouldn't surprise me if you haven't got a ~/.lastlog . but who knows if that's the case for him, if i were him, i would really change that :)
Johannes Schaub - litb
.lastlogin seems to be a bashism. If you use any other shell, it won't be there. So, yes, the original idea is poor.
bortzmeyer
+3  A: 

Okay, in a pure shell script, you probably want to use sort(1) with blank as your field sep. something like

$ find /ifshome/user/ -name .lastlogin -print |
  xargs sort --key=8,8 --key=4,4 --key=5,5

(warning, untested.)

You might find it easier to use python or perl, as they have better date-handling optins.

Charlie Martin
Doesn't this lose the names of the files - and hence of the users?
Jonathan Leffler
nice, i had no idea sort could be used to sort by months. however, i wouldn't use find. it will recurse into subdirectories - you don't want that. why not sort --key=8,8 --key=4,4 --key=5,5 /ifshome/*/.lastlogin ?
Johannes Schaub - litb
JL: Well, that's why it's "something like". Gotta leave something as an exercise for the student. litb: I wasn't sure it was guaranteed to always be in the topmost directory. If it is, then we're equivalent, ls maybe a skosh faster. Also, the key needs a flag to sort months correctly.
Charlie Martin
+4  A: 

You may find the last command is helpful to you. It will list the last N users who logged in, or the users logged in at a particular time, etc. man page

rmeador
A: 

It can be accomplished relatively easily in PERL with the following code:

#!/usr/bin/perl

use strict;
use Time::Local ();

my $dir = "/ifshome";

my $month = {
  'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5,
  'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11,
};

my $expire = time() - (86400 * 30 * 6);

foreach my $home (<$dir/*>) {
  open(F,"$home/.lastlogin");
  chomp(my $line = <F>);

  if ($line =~ /^Last Login:\s+\w{3}\s+(\w{3})\s+(\d{2})\s+(\d{2}):(\d{2}):(\d{2})\s+\w+\s+(\d{4})/) {
    my $ts = Time::Local::timelocal($5,$4,$3,$2,$month->{$1},$6-1900);
    if ($ts < $expire) {
      my($user) = (split(/\//,$home))[-1];
      print "$user account is expired\n";
    }
  }
}
Jamie
+1  A: 

Ok, here is my silly way (untested!) using a pure shell script parsing your file.

The date command can parse a date string, and output the seconds since 1970. Subtract them from the current seconds, and divide by the amount of seconds one month takes. Print that value together with the users path.

for i in /ifshome/*/.lastlogin; do
    dates=$(cat $i | grep "Last Login:" | cut -d: -f 2-)
    if [ ! -z "$dates" ]; then
      months=$(( ($(date +%s) - $(date -d "$dates" +%s)) / (60*60*24*31) ))
      echo $months $i
    fi
done

Sort the output using sort -n and pipe that into less then you can browse the list of users and their activity.

For a non-hackish way, consider Juan's lastlog idea. It's on my linux too.

Johannes Schaub - litb
See below my version if your code, some minor changes to suit my needs. Thanks!
DV
Warning: only GNU date can do it so the result may depend on the Unix you use (yes, the OQ was tagged linux but nothing forces a linux-based system to use GNU date).
bortzmeyer
A: 

Here's some minor changes to litb's code. It can take # of months as a parameter, and it outputs strictly username followed by months since changed:

oldusers.sh:

echo "Purpose: Parse /ifshome and find dates in .lastlogin files that are older than MONTHS months."
echo "Usage: ./oldusers.sh [MONTHS=6]"
echo ""

case $# in
1)
monthmin=$1
;;
*)
monthmin=6
;;
esac

if [ "${monthmin//[^0-9]/}" != $monthmin ]; then echo "$monthmin is NaN";
else
 for i in ./*/.lastlogin; do
    dates=$(cat $i | grep "Last Login:" | cut -d: -f 2-)
    if [ ! -z "$dates" ]; then
      months=$(( ($(date +%s) - $(date -d "$dates" +%s)) / (60*60*24*30) ))
      user=$(echo $i | cut -d/ -f 2- | cut -d/ -f -1)
      if test $months -ge $monthmin; then echo "$user: $months months ago"; fi
    fi
 done
fi
DV
+1  A: 

It seems to me that the contents of the file would likely echo the modification timestamp of the file, so you could use a much simpler command:

 find /ifshome -name .lastlogin -mtime +182 -print

Print all the files called .lastlogin with a modification time over 182 days old (choose your own approximation to 6 months).

Jonathan Leffler