Shell script to compare dates from multiple files in Linux
I have many home directories under / ifshome on Linux. I want to find out which users have not logged in in the last 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 create a wrapper script that can parse the .lastlogin file in each user's home directory and list those directories that have not been logged in in the last 6 months.
source to share
Ok, here's my silly way (untested!) Using a clean shell script, parsing your file.
The command date
can parse a date string and output seconds since 1970. Subtract them from the current seconds and divide by the number of seconds, which takes one month. Print this value along with the custom 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 result with sort -n
and move it to less
, then you can view the list of users and their activity.
For an uncommon way, consider Juan's bad debt idea. This is also on my Linux.
source to share
You may find a command last
that is useful to you. It will list the last N users who have logged in, or users registered at a specific time, etc. reference page
source to share
Okay, in a clean shell script, you probably want to use sort (1) with a space as the sep field. 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 options for handling date.
source to share
It seems to me that the contents of the file are likely to echo the file's modified timestamp, so you can use a much simpler command:
find /ifshome -name .lastlogin -mtime +182 -print
Print all files named .lastlogin with modification times within 182 days (choose your own approximation to 6 months).
source to share
This can be done 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";
}
}
}
source to share
Here are some minor changes to the litb code. This can take several months as a parameter, and it outputs the strictly username followed by months since they were 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
source to share