A client wanted login session statistics to be included in the daily logwatch reports he received.
The kind of stats he was looking for come from the last command:
[root@asus ~]# last| head -25 mabboud pts/0 sainsw Thu Nov 1 18:12 still logged in cmurphy pts/2 brkdtp2970 Thu Nov 1 16:59 - 17:01 (00:01) akozak pts/2 sfddtp2889 Thu Nov 1 16:51 - 16:52 (00:00) ghughes pts/1 brklap026 Thu Nov 1 16:37 - 17:40 (01:03) creading pts/1 ivmdtp2958 Thu Nov 1 16:19 - 16:26 (00:06) awall pts/0 lavlap009 Thu Nov 1 15:56 - 17:36 (01:39) hnisbet pts/16 brmdtp005 Thu Nov 1 15:02 - 16:58 (01:56) dbrache pts/39 geedtp2923 Thu Nov 1 14:44 - 15:46 (01:02) cmcbean pts/44 brklap011 Thu Nov 1 14:30 - 14:32 (00:01) dbrache pts/39 geedtp2923 Thu Nov 1 14:20 - 14:43 (00:22) jgregory pts/42 brklap3053 Thu Nov 1 14:15 - 17:28 (03:12) awall pts/41 thtmg Thu Nov 1 14:13 - 14:40 (00:26) rraverty pts/40 brklap020 Thu Nov 1 14:10 - 15:14 (01:04) dbrache pts/39 geedtp2923 Thu Nov 1 13:44 - 14:19 (00:35) cmcbean pts/34 brklap011 Thu Nov 1 13:39 - 14:48 (01:08) dfurboro pts/3 sfdlap002 Thu Nov 1 13:29 - 16:20 (02:51) mhinton pts/3 sfdlap001 Thu Nov 1 13:11 - 13:22 (00:11) znyparas pts/3 brmdtp3023 Thu Nov 1 12:53 - 12:56 (00:03) mhinton pts/3 sfdlap001 Thu Nov 1 12:48 - 12:52 (00:03) mhinton pts/3 sfdlap001 Thu Nov 1 12:14 - 12:22 (00:08) cmurphy pts/41 brkdtp2970 Thu Nov 1 11:36 - 11:36 (00:00) rvlasvel pts/10 sfddtp002 Thu Nov 1 10:55 - 16:41 (05:45) rvlasvel pts/20 sfddtp2887 Thu Nov 1 10:52 - 16:41 (05:48) znyparas pts/10 btylap044 Thu Nov 1 10:52 - 10:54 (00:02) wpithous pts/49 btylap044 Thu Nov 1 10:41 - 11:03 (00:21) . . .
The twofold challenge I faced was:
- Write a simple script to gather yesterday’s login stats from the last command
- Modify logwatch to include these stats in a seamless way in the daily logwatch report
1. Yesterday’s session stats
The last command provides a simple option:
last -t YYYYMMDDHHMMSS
…which can be used to show a list of last logged in users as of the specified date / time.
But I found this option didn’t work as advertised for some reason – I always seemed to get more than just yesterday’s login sessions. It usually went beyond yesterday and included other days as well.
The customer simply wanted a snapshot of the login sessions for yesterday only. The best approach seemed to be of the form:
last |grep [yesterday's date] > /var/log/lastsessions
Once I could get yesterday’s date massaged into the same output format as the last command displayed it, the grep would succeed.
This took a bit of careful study – I worked out that the last command date output was formatted as follows:
- Always fitted into 10 columns, e.g:
Thu Nov 1 Wed Oct 31
- …notice that the day column is right-justified, and had no ‘0’ padding for single digit days
I also discovered that yesterday’s date could easily be obtained in the correct format by using:
[root@asus ~]# date --date=yesterday Wed Oct 31 18:35:16 EST 2012
…and, confirming the formatting is correct for single-digit dates:
[root@asus ~]# date --date=tomorrow Fri Nov 2 18:36:55 EST 2012
So now my grep command could be placed into a script, like this:
[root@asus ~]# cat /usr/local/bin/lastSessions.sh #!/bin/bash # Get yesterday's date in the correct format for grep'ing # We only need the first 10 columns of output YESTERDAY=`date --date=yesterday|cut -c1-10` # Get yesterday's login sesssions, sorted by name and filed away for logwatch use last |grep "${YESTERDAY}" |sort >/var/log/lastsessions 2>&1 exit 0
Typical output of the above script looks like this:
[root@asus ~]# cat /var/log/lastsessions aarthur pts/19 btydtp2926 Wed Oct 31 08:06 - 08:07 (00:00) ajones pts/7 10.191.1.3 Wed Oct 31 07:23 - 15:58 (08:34) akarpath pts/0 vildtp003 Wed Oct 31 05:00 - 13:13 (08:13) askinner pts/15 sp1lap001 Wed Oct 31 07:46 - 16:06 (08:20) bhoar pts/14 sp1lap003 Wed Oct 31 07:38 - 16:13 (08:34) dchua pts/0 ml1dtp2898 Wed Oct 31 13:49 - 16:50 (03:00) dchua pts/22 sp1lap032 Wed Oct 31 08:50 - 17:03 (08:12) dsmedley pts/1 btylap005 Wed Oct 31 05:07 - 12:52 (07:45) garmstro pts/21 sp1dtp022 Wed Oct 31 08:36 - 14:45 (06:08) garmstro pts/4 sp1dtp022 Wed Oct 31 05:30 - 16:10 (10:39) garmstro pts/5 sp1dtp022 Wed Oct 31 07:07 - 07:11 (00:04) jlangrid pts/12 sp1dtp2938 Wed Oct 31 07:37 - 16:30 (08:52) kwarne pts/9 ml1dtp2898 Wed Oct 31 07:27 - 16:50 (09:23) ndrury pts/13 sp1lap015 Wed Oct 31 07:38 - 09:26 (01:48) ndrury pts/2 sp1lap015 Wed Oct 31 14:12 - 14:59 (00:47) nfitzger pts/1 kaldtp2952 Wed Oct 31 13:54 - 16:03 (02:09) nfitzger pts/19 kaldtp2952 Wed Oct 31 08:10 - 12:51 (04:40) npavitt pts/2 btydtp2902 Wed Oct 31 05:19 - 12:24 (07:05) phincksm pts/6 sp1dtp025 Wed Oct 31 06:56 - 15:52 (08:56) ppezzali pts/11 ml1dtp018 Wed Oct 31 07:35 - 15:53 (08:18) rboyd pts/18 bundtp2883 Wed Oct 31 08:05 - 15:52 (07:47) root pts/17 btylap044.ap01.a Wed Oct 31 07:57 - 11:59 (04:02) root tty7 :0 Wed Oct 31 08:09 still logged in rpagano pts/13 sp1lap030 Wed Oct 31 09:43 - 16:30 (06:47) sai pts/0 saitest Wed Oct 31 02:14 - 02:45 (00:30) scarter pts/23 ml1dtp2911 Wed Oct 31 09:15 - 09:16 (00:01) scarter pts/23 ml1dtp2911 Wed Oct 31 09:20 - 09:24 (00:04) scarter pts/23 ml1dtp2911 Wed Oct 31 09:50 - 09:51 (00:01) scarter pts/23 ml1dtp2911 Wed Oct 31 09:52 - 10:06 (00:13) scarter pts/3 sp1dtp2914 Wed Oct 31 14:35 - 16:31 (01:55) scarter pts/5 ml1dtp2911 Wed Oct 31 07:23 - 09:16 (01:53) scarter pts/5 ml1dtp2911 Wed Oct 31 09:17 - 16:14 (06:57) scarter pts/8 ml1dtp2911 Wed Oct 31 07:24 - 10:04 (02:40) scarter pts/8 ml1dtp2911 Wed Oct 31 10:06 - 16:14 (06:08) sfick pts/1 sp1dtp2915 Wed Oct 31 16:29 - 16:31 (00:02) sfick pts/20 sp1dtp2915 Wed Oct 31 08:10 - 16:25 (08:15) sleatham pts/10 weldtp3019 Wed Oct 31 07:32 - 16:07 (08:34) ssmith pts/5 ml1dtp2911 Wed Oct 31 06:49 - 06:53 (00:03) ssmith pts/5 ml1dtp2911 Wed Oct 31 06:56 - 06:57 (00:00) wskirrow pts/16 bundtp2884 Wed Oct 31 07:55 - 15:32 (07:36)
2. Configuring Logwatch to display the stats
This was tricky as I had always wanted to customise logwatch but never had need to until this customer’s request
Online help for logwatch is available via the Sourceforge Forums here:
…and customisation documentation seems scarce to find.
So, here’s a summary of what needs to be done to customise logwatch to include the output of the above script in the daily report
First, make sure logwatch is in fact installed in your Linux distro. Then for Ubuntu users, start in /etc/logwatch – which ends up looking like this:
[root@asus logwatch]# tree -Cf . ├── ./conf │ ├── ./conf/ignore.conf │ ├── ./conf/logfiles │ │ └── ./conf/logfiles/lastsessions.conf │ ├── ./conf/logwatch.conf │ ├── ./conf/override.conf │ └── ./conf/services │ └── ./conf/services/lastsessions.conf └── ./scripts └── ./scripts/services └── ./scripts/services/lastsessions
Three files need to be created:
[root@asus logwatch]# cat ./conf/logfiles/lastsessions.conf LogFile = lastsessions
…this tells logwatch to use the lastsessions file as the log file to check, found in the default /var/log/ location
[root@asus logwatch]# cat ./conf/services/lastsessions.conf Logfile = lastsessions Title = "Last Login Sessions Accounting"
…this tells logwatch the name of the log file to check, and the title to be used in the final logwatch report
[root@asus logwatch]# cat ./scripts/services/lastsessions #!/usr/bin/perl while (defined($ThisLine = <STDIN>)) { print $ThisLine; } exit(0);
…lastly, this is the script logwatch will use against the log file previously defined, named the /var/log/lastsessions file. It’s a simple Perl script which prints each line of the /var/log/lastsessions file to standard output – the output of course ends up in the logwatch report.
NOTE: Make sure the script has execute permissions
3. Putting it all together
Once the above mods are made, the last thing to do is run the /usr/local/bin/lastSessions.sh script as a cronjob, before the logwatch cronjob runs at 4am. I run it like this:
[root@asus ~]# crontab -l 0 2 * * * /usr/local/bin/lastSessions.sh >/dev/null 2>&1
…everyday at 2am, the lastSessions.sh script produces the /var/log/lastsessions output file. Then at 4am, logwatch parses the output file and includes the output in it’s report.
I like to run logwatch at detail level 10 (High), and have it produce an HTML formatted email report, so that navigating the various sub-reports is as easy as clicking the report headings links. You configure logwatch to do this like so:
[root@asus ~]# cd /usr/share/logwatch/default.conf
…and make sure the following parameters are set in logwatch.conf:
LogDir = /var/log TmpDir = /var/cache/logwatch MailFrom = Logwatch Print = No Range = yesterday Detail = High Service = All mailer = "sendmail -t"
NOTE: Default email goes to root, change this by modifying the MailTo = <address> parameter. I use an alias of email addresses from /etc/aliases which I name logwatchUsers
Lastly, I make sure the logwatch output format is HTML, as follows:
[root@asus ~]# cat /etc/cron.daily/0logwatch #!/bin/bash DailyReport=`grep -e "^[[:space:]]*DailyReport[[:space:]]*=[[:space:]]*" /usr/share/logwatch/default.conf/logwatch.conf | head -n1 | sed -e "s|^\s*DailyReport\s*=\s*||"` if [ "$DailyReport" != "No" ] && [ "$DailyReport" != "no" ] then logwatch --output HTML fi
Typical logwatch output email will look like this (the headings are usually HTML links):
* LOGWATCH Summary * System Configuration * Cron * httpd * Last Login Sessions Accounting <-- This is the link to our report :-) * pam_unix * samba . . . Last Login Sessions Accounting Last Login Sessions Accounting Begin aarthur pts/19 btydtp2926 Wed Oct 31 08:06 - 08:07 (00:00) ajones pts/7 10.191.1.3 Wed Oct 31 07:23 - 15:58 (08:34) akarpath pts/0 vildtp003 Wed Oct 31 05:00 - 13:13 (08:13) askinner pts/15 sp1lap001 Wed Oct 31 07:46 - 16:06 (08:20) bhoar pts/14 sp1lap003 Wed Oct 31 07:38 - 16:13 (08:34) dchua pts/0 ml1dtp2898 Wed Oct 31 13:49 - 16:50 (03:00) dchua pts/22 sp1lap032 Wed Oct 31 08:50 - 17:03 (08:12) . . ssmith pts/5 ml1dtp2911 Wed Oct 31 06:49 - 06:53 (00:03) ssmith pts/5 ml1dtp2911 Wed Oct 31 06:56 - 06:57 (00:00) wskirrow pts/16 bundtp2884 Wed Oct 31 07:55 - 15:32 (07:36) Last Login Sessions Accounting End
Happy monitoring!
Thanks for your help!!!
…you’re very welcome Dh Ch.
Michael