Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Member Watcher

by penguinfuz (Pilgrim)
on Oct 22, 2002 at 14:54 UTC ( #207094=sourcecode: print w/replies, xml ) Need Help??
Category: Web Stuff
Author/Contact Info penguinfuz at wonderwaylabs dot com
Description: The script was written to report the daily changes of web users, New, Cancelled, and Remaining. It is suited for a specific system but with slight modification the script could be used elsewhere.

For this specific instance we have 2 services storing web user names in multiple files (ala htpasswd). Once per day we read and log the usernames, finding the difference between today and yesterday (if there was a yesterday), and email the report to the relevent parties.
#! /usr/bin/perl -w

use strict;

my ($repdate,$date,$ufile1,$ufile2,$track1,$track2,$tmpfile);
chomp($repdate  = `/bin/date "+%A %d %B %Y"`);
$date   = `date +%d/%m/%y`;
$ufile1 = "/path/to/htpasswd-ONE";
$ufile2 = "/path/to/htpasswd-TWO";
$track1 = "/path/to/log/location/service1";
$track2 = "/path/to/log/location/service2";
$tmpfile= "/tmp/";

# get users from PREVIOUS htpasswd
my @traw1 = parse_trackfile($track1);
my @traw2 = parse_trackfile($track2);
my @tusers_service1 = sort @traw1;
my @tusers_service2 = sort @traw2;

# get current users from htpasswd
my @uraw1 = parse_htpasswd($ufile1,$track1);
my @uraw2 = parse_htpasswd($ufile2,$track2);
# sort lexically -- (alphabetically)
my @cusers_service1 = sort @uraw1;
my @cusers_service2 = sort @uraw2;

calculate_users("Service 1",\@cusers_service1,\@tusers_service1);
calculate_users("Service 2",\@cusers_service2,\@tusers_service2);

# ---------------
# subroutines
# ---------------

sub parse_trackfile {
  my $trackfile = shift;
  chomp (my $now = `date +%Y.%m.%d`);
  my @users;
  open FILE,$trackfile or die "Cannot open $trackfile: $!";
    while (<FILE>) {
      next if $_ =~ /^$/;
      next if $_ =~ /^\#$/;
      push @users,$_;
  close FILE or warn $!;
  return @users;

sub parse_htpasswd {
  my ($ufile,$trackfile) = @_;
  my (@users,$user,$pass);
  open TRACK,">$trackfile" or die "Cannot open $trackfile: $!\n";
  open FILE,$ufile or die "Cannot open $ufile: $!\n";
    while (<FILE>) {
      next if $_ =~ /^$/;
      next if $_ =~ /^\#$/;
      ($user,$pass) = split /:/;
      print TRACK "$user\n";
      push @users, $user;
  close FILE or warn $!;
  close TRACK or warn $!;
  return @users;

sub calculate_users {
  my ($service,$current,$previous) = @_;
  my %current  = map { $_ => 1 } @$current;
  my %previous = map { $_ => 1 } @$previous;

  # calculate NEW users
  my @new_users = grep (!defined $previous{$_},@$current);
  # calculate CANCELLED users
  my @cancelled_users = grep (!defined $current{$_},@$previous);
  # calculate REMAINING users
  my @remaining_users = grep($current{$_},@$previous);

  my ($new_cnt,$canc_cnt,$rem_cnt);
  if (@new_users) {
    $new_cnt = $#new_users;
  } else {
    $new_cnt = "0";
  if (@cancelled_users) {
    $canc_cnt = $#cancelled_users;
  } else {
    $canc_cnt = "0";
  if (@remaining_users) {
    $rem_cnt = $#remaining_users;
  } else {
    $rem_cnt = "0";

  # open temp file for writing:
  open TMP, ">$tmpfile" or die $!;
    # print the report suitable for emailing
    print TMP "$service: Member Information for $repdate\n\n";

    print TMP "New Members:\t\t $new_cnt\n";
    print TMP "Cancelled Members:\t $canc_cnt\n";
    print TMP "Remaining Members:\t $rem_cnt\n";
    print TMP "\n";

    print TMP "------- New ------------------\n";
    print TMP "\t$_\n" for @new_users;
    print TMP "------------------------------\n\n";
    print TMP "------- Cancelled ------------\n";
    print TMP "\t$_\n" for @cancelled_users;
    print TMP "------------------------------\n\n";
    print TMP "------- Remaining ------------\n";
    print TMP "\t$_\n" for @remaining_users;
    print TMP "------------------------------\n";
  close TMP or warn $!;


sub email_daily_report {
  my ($service) = @_;
  chomp (my $hostname = `/bin/hostname`);
  open TMP,$tmpfile or die "Cannot open $tmpfile: $!\n";
  open(SENDMAIL, "|/usr/lib/sendmail -oi -t")
        or die "Cannot fork for sendmail: $!\n";

    print SENDMAIL "From: MemberWatch <nobody\@${hostname}>\n";
    print SENDMAIL "To: Webmaster <webmaster\@somedomain.dom>\n";
    print SENDMAIL "Cc: Accounting <accounting\@somedomain.dom>\n";
    print SENDMAIL "Subject: [$service] Members: $repdate\n";
    print SENDMAIL "\n";

    while (<TMP>) {
      print SENDMAIL "$_";

  close(SENDMAIL) or warn "Oops, sendmail did not close nicely";
  close TMP or warn $!;

sub clean_up {
  unlink $tmpfile or die "Cannot unlink $tmpfile: $!\n";
Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://207094]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2019-12-07 12:46 GMT
Find Nodes?
    Voting Booth?
    Strict and warnings: which comes first?

    Results (160 votes). Check out past polls.