3 # Copyright (C) 2013, Jason Self
5 # This program gives you software freedom; you can copy, modify, convey,
6 # and/or redistribute it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 3 of the
8 # License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
15 # You should have received a copy of the GNU General Public License along
16 # with this program in a file called 'GPLv3.txt'. If not, see
17 # http://www.gnu.org/licenses/gpl-3.0-standalone.html or write to the:
18 # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor
19 # Boston, MA 02110-1301, USA.
21 # Documentation (in pod format) at the bottom of this file
30 use YAML qw(LoadFile);
31 use File::ReadBackwards;
34 #-----------------------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------------------
37 my $file_lastrun = "user-tracker.run";
38 my $file_log = "user-tracker.log";
40 my ($output, $help, $man, $now, $last_run, %last_login);
43 #-----------------------------------------------------------------------------------------
45 #-- print usage if the script is not called properly
47 GetOptions( 'output=s' => \$output, 'help|?' => \$help, man => \$man);
48 pod2usage(-exitstatus => 0, -verbose => 2) if $man;
49 pod2usage(1) if $help;
51 $now = scalar localtime;
53 #-- read output log and store values in %last_login
54 $output = $file_log if not defined $output;
55 if ( open LOG, "<$output" )
60 ($date, $user) = split ' - ', $_;
61 $last_login{$user} = $date;
66 warn "Can't open $output: $! ... probably first run\n";
68 open LOG, ">$output" or die "Can't open $output: $!\n";
70 if ( open LASTRUN,"<$file_lastrun" )
73 $last_run = ParseDate($date);
77 warn "Can't open $file_lastrun: $! ... parsing all lines of the log files\n";
78 $last_run = ParseDate("Jan 01 00:00 1970");
81 #-- $config is a reference to a structure like this:
83 # '/var/log/mail.log' => [
85 # 'pattern' => '^(.{15}).*Login: user=<([^>]+).*',
91 # '/var/log/auth.log' => [ ... etc
92 my $config = LoadFile("user-tracker.cfg") or die "Can't open config file: $!\n";
94 foreach my $file ( sort keys %{$config} )
96 my $fh = File::ReadBackwards->new($file) or warn "Can't open $file: $!\n" and next;
97 while ( defined(my $line = $fh->readline()) )
99 foreach my $element ( @{$config->{$file}} )
101 ($date, $user) = (undef, undef);
103 #-- store values in $date and $user
104 (${$element->{first}}, ${$element->{second}}) = ($line =~ $element->{pattern});
106 #-- skip line if $date not defined
107 next if ( not defined $date );
109 #-- stop processing the file if the date is earlier than $last_run
110 last if ( Date_Cmp(ParseDate($date),$last_run) < 0 );
112 #-- line matches, update %last_login
113 if ( not exists $last_login{$user} or Date_Cmp(ParseDate($date),ParseDate($last_login{$user})) > 0 )
115 $last_login{$user} = $date;
121 #-- save to output file
122 foreach ( sort { ParseDate($last_login{$a}) cmp ParseDate($last_login{$b}) } keys %last_login )
124 print LOG "$last_login{$_} - $_\n";
127 open LASTRUN, ">$file_lastrun" or die "Can't open $file_lastrun: $!\n";
133 #-----------------------------------------------------------------------------------------
143 usertracker.pl [-o output] [-h] [-man]
151 name of output file, if not provided, write to file specified in $file_log
155 display help information and exits
159 display a more detailed help information, including author and changelog
165 Scans specified log files for information about logged-in users and adds the list of
166 logged users to a file
170 Jason Self (j@jxself.org)
176 =item Feb 03, 2013 : v1.0