#!/usr/bin/perl # # History: # # -------Version 0.0.2-------------------------------------------------------------------------------- # 17-10-02 Z Written. # 20-10-02 Z Modified to give QMAIL support. # 23-10-02 Z Fixed the bug of continuous email. # Z Added codes to warn user on every 2% increase from threshold. # 30-10-02 Z Added the POD, changed some documention, added the Quota module check, # System's quota check and /etc/quotawarn.msg generation sub routine. # 31-10-02 Z Fixed the system's quota checking module. # #--------Version 0.0.2a------------------------------------------------------------------------------- # # 12-12-02 Z Added README for the man page, added one more example, fixed some # typos. #--------Version 0.0.2b------------------------------------------------------------------------------- # 11-04-03 Z Fixed a bug in the hasQuotaSupport subroutine. The bug was pointed out # by Olivier Bekoin . # # Author: Ziaur Rahman # # Synopsis: # # File quotadm # # Program Name Quota Administration (QUOTA ADMinistration). # # Version 0.0.2b # # Description This script shows user quotas in the system, and if --email is mentioned # it will email a warning msg to users when the threshold is reached or exceeded. # # Variables $msgfile - Default: /etc/quotawarn.msg, this file contains the email that will # be sent to the users whose quota has reached or exceeded $threshold. # Inside this file you can use %user to mention the Username, %print to print the # table of quota information, %quota to how much quota is assigned to the user. # # $mta - Default: /usr/lib/sendmail, this is where you set the location of # your MTA. Currently, this script only supports SENDMAIL and QMAIL. If you # are using QMAIL, please enter the location of your qmail-inject. # # $echo - Default: /bin/echo, this is the location of the echo command which # is used to send mail for QMAIL. # # $threshold - Default: 90, this is the "high water mark" for the users. When # user's disk usage equals/exceeds [>=] user's quota threshold, i.e. more # than or equal to 90% of user's quota, then the script will send a warning # message (/etc/quotawarn.msg) to the user. Actcually, the script will send the # warning msg on every 2% increase after the quota of the user reaches his/her # threshold if the user has not cleared his mail or freed up some disk space. ########################################################################################################## $VERSION = "0.0.2b"; # # Configurable Global variables start here... # # Define the global variables here $msgfile = "/etc/quotawarn.msg"; $mta = "/usr/lib/sendmail"; # define your MTA location here. $echo = "/bin/echo"; $threshold = 90; # # Configurable Global variables end here... # # Subroutine to check whether system has Quota enabled in the file system or not. sub checkQuota { ($loc) = @_; chomp(@grepres = `/bin/grep quota $loc`); foreach $line (@grepres) { ($dummy,$home) = split(/\s|\t/,$line); if ((-e ("$home/aquota.user")) || (-e ("$home/aquota.group"))) { if ((-s ("$home/aquota.user")) || (-s ("$home/aquota.group"))) { return 1; } } elsif ((-e ("$home/quota.user")) || (-e ("$home/quota.group"))) { if ((-s ("$home/quota.user")) || (-s ("$home/quota.group"))) { return 1; } } else { return 0; } } } sub hasQuotaSupport { my @locs = ('/etc/mtab','/etc/mnttab','/etc/fstab'); foreach $loca (@locs) { if (-e "$loca") { if (`/bin/grep -c quota $loca` == 1) { my $res = checkQuota("$loca"); return $res; } } } } # First, check whether the system has Quota support for its filesystem or not: if (&hasQuotaSupport == 0) { print "\tYour system seems to be missing quota support in the filesystem...\n"; print "\tYou need to enable quota in your filesystem first to use this script...\n"; print "\n"; exit; } # Subroutine to check whether Quota module for Perl is installed or not. sub hasModule { use ExtUtils::Installed; local ($gmodule) = @_; chomp($gmodule); my $instmod = ExtUtils::Installed->new(); foreach my $module ($instmod->modules()) { if ($module =~ "$gmodule") { return 1; } } return 0; } # Check whether the system has the Quota module for Perl installed or not: if (&hasModule("Quota") == 0) { print "\n\n\tSorry your system does not have Quota module for Perl installed.\n"; print "\tPlease download the Quota module for Perl from:\n"; print "\t\thttp://search.cpan.org/CPAN/authors/id/T/TO/TOMZO/Quota-1.4.6.tar.gz\n"; print "\tand install it.\n"; print "\n"; exit; } use Quota; while(1) { #$path = "/"; $path = $home; while(1) { $dev = Quota::getqcarg($path); if(!$dev) { warn "$path: mount point not found\n"; } last; } redo if !$dev; ## Check if quotas are present on this filesystem if($dev =~ m#^[^/]+:#) { print "$dev is a remote file system\n"; last; } elsif(Quota::sync($dev) && ($! != 1)) { # ignore EPERM warn "Quota::sync: ".Quota::strerr."\n"; warn "Choose another file system - quotas not functional on this one\n"; } else { #Quotas are present on this filesystem (sync ok) last; } } sub sendemail { local ($user,$printit,$quotaa) = @_; $quotadec = sprintf("%0.2d",$quotaa); open (MSGFILE, "$msgfile") or die "can not open $msgfile\n"; while () { $line = $_; $line =~ s/%user/$user/; $line =~ s/%print/$printit/; $line =~ s/%quota/$quotadec/; $msg .= $line; } if ($mta =~ "sendmail") { open (SENDMAIL, "| $mta -t -n") or die "Cannot open sendmail from $sendmail\n";; print SENDMAIL < 100) { print "Threshold value cannot be more that 100,\nplease change the value in \$threshold\n"; exit; } ($name,$coded_pwd,$uid,$gid,$x,$y,$z,$gcos,$home,$shell) = getpwnam($user); ($bc,$bs,$bh,$bt,$fc,$fs,$fh,$ft) = Quota::query($dev, $uid); if(defined($bc)) { my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($bt); $bt = sprintf("%04d-%02d-%02d/%02d:%02d", $year+1900,$mon+1,$mday,$hour,$min) if $bt; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($ft); $ft = sprintf("%04d-%02d-%02d/%02d:%02d", $year+1900,$mon+1,$mday,$hour,$min) if $ft; #print "Usage and limits for $user are $bc ($bs,$bh,$bt) $fc ($fs,$fh,$ft)\n\n"; goto ALL if $pargv eq "--all"; if ($bs != 0) { ALL:{ $usageinMB = $bc/1024; $quotainMB = $bs/1024; $percentUsage = (($bc/$bs)*100) if $bs != 0; $perUsage = sprintf ("%.2f%s",$percentUsage,"%"); if ($percentUsage >= $threshold) { $diffth = ($percentUsage - $threshold); $diffthresh = sprintf ("%.2f%s%s",$diffth,"%","-"); } elsif ($threshold >= $percentUsage) { $diffth = ($threshold - $percentUsage); $diffthresh = sprintf ("%.2f%s%s",$diffth,"%","+"); } $arrayi = 1; for ($i=$threshold;$i<=100;$i=$i+2) { $thresh[$arrayi] = $i; $arrayi = $arrayi + 1; } $wsent = 0; if (-e("$gcos/.quotawarn")) { open (QW,"+<$gcos/.quotawarn"); while () { chomp($wsent = $_); } } for ($j=1;$j<=$arrayi;$j++) { if (($percentUsage >= $thresh[$j]) && ($percentUsage < $thresh[$j+1])) { if ($email eq "--email") { $printem .= sprintf ("%15s%15s%15s%15s%15s%15s\n\n","UserName","Usage(MB)","Quota(MB)","Usage(%)","ThreshHold(%)","Diff(+/-)"); $printem .= sprintf ("%15s%15.2f%15.2f%15s%15s%15s\n",$user,$usageinMB,$quotainMB,$perUsage,$thresholds,$diffthresh); if (($wsent != $thresh[$j]) && ($bs != 0)) { &sendemail($user,$printem,$quotainMB); open (QW,">$gcos/.quotawarn"); print QW "$thresh[$j]"; } } } } printf ("%15s%15.2f%15.2f%15s%15s%15s\n",$user,$usageinMB,$quotainMB,$perUsage,$thresholds,$diffthresh) if $email ne "--email"; close (QW) if defined(QW); } } } else { warn "Quota::query($dev,$uid): ",Quota::strerr,"\n\n"; } } sub doall { local($argvp,$mail) = @_; open(PASSWD,"/etc/passwd"); while() { chop; ($userid,$dpw,$uin) = split (':',$_); &doquota($userid,$mail,$argvp); } close PASSWD; } sub generatemsg { if (-e "/etc/quotawarn.msg") { BACKYN: print "/etc/quotawarn.msg file exists!\n"; print "Do you want to overwrite it? (Y/N): "; chomp($yn = ); if (($yn eq "Y") || ($yn eq "y")) { open(GENMSG,">/etc/quotawarn.msg") or die "Can't create file /etc/quotawarn.msg.\n"; } elsif (($yn eq "N") || ($yn eq "n")) { print "\nYou chose not to overwrite the file /etc/quotawarn.msg.\n"; print "Please backup your data in the file /etc/quotawarn.msg and try again.\n"; exit; } else { goto BACKYN; } } else { open(GENMSG,">/etc/quotawarn.msg") or die "Can't create file /etc/quotawarn.msg.\n"; } print GENMSG << 'GENEOF'; From: "Quota Administrator" To: %user@domain.com Subject: Warning: Your disk usage is close to or over quota!!! You account is extremely close to or over your quota limit (%quota). Once the quota limit is reached, no more data can be stored. That includes you mail directories also. So, mail will not be saved. Consider moving some data to another location or increasing the limit. Please see your quota details below: %print GENEOF print "\nThe file /etc/quotawarn.msg is generated.\n"; print "Please edit the From: and To: field to add your domain name.\n"; print "Also you use %user to mention the Username, %print to print the table of quota information,\n"; print "and %quota to how much quota is assigned to the user.\n\n"; } sub usage { print "\nUsage: quotadm OPTION1 [OPTION2]\n"; print "Show quota information of a particular user or all users, send warning email on threshold.\n\n"; print "-u \t\tSingle user's quota information with threshold info. (-u=OPTION1, =OPTIONS2)\n"; print "--all-quota\t\tShow those user's quota information whose quota is on. (OPTION1)\n"; print "--all\t\t\tShow all user's quota information. (OPTION1)\n"; print "--email\t\t\tEmail the user if he/she has reached/exceeded threshold for quota. (OPTION2)\n"; print "--genmsg\t\tGenerate the default email template in /etc/quotawarn.msg file. (OPTION1)\n"; print "\n"; print "Examples of combining OPTIONS:\n\n"; print "Example 1: \n\"quotadm -u tom --email\" \n- will send an email to tom if his quota has reached or exceeded the threshold.\n\n"; print "Example 2: \n\"quotadm --all-quota --email\" \n- will send an email to each user whose quota has reached or exceeded the threshold.\n"; print "\n"; exit; } # # The main program starts here. # $argv1 = $ARGV[0]; $argv2 = $ARGV[1]; $argv3 = $ARGV[2]; chomp ($argv1); chomp ($argv2); chomp ($argv3); if ($argv1 eq "-u") { printf ("%15s%15s%15s%15s%15s%15s\n\n","UserName","Usage(MB)","Quota(MB)","Usage(%)","ThreshHold(%)","Diff(+/-)") if $argv3 ne "--email"; &doquota($argv2,$argv3); } elsif ($argv1 eq "--all-quota" || $argv1 eq "--all") { &usage if defined($argv3); printf ("%15s%15s%15s%15s%15s%15s\n\n","UserName","Usage(MB)","Quota(MB)","Usage(%)","ThreshHold(%)","Diff(+/-)") if $argv2 ne "--email"; &doall($argv1,$argv2); } elsif ($argv1 eq "--genmsg") { &generatemsg(); } else { &usage(); } =pod =head1 NAME quotadm - Show quota information of a particular user or all users, send warning email on threshold. The name is derived from "Quota Administration [QUOT(A A)DMinistration]". =head1 SYNOPSIS quotadm OPTION1 [OPTION2] =head1 DESCRIPTION This script shows user quotas in the system, and if "--email" is mentioned it will email a warning msg to users when the threshold is reached or exceeded. Following are the options that the script currently accepts: =item I<-u > Single user's quota information with threshold info. (-u=OPTION1, =OPTIONS2) =item I<--all-quota> Show those user's quota information whose quota is on. (OPTION1) =item I<--all> Show all user's quota information. (OPTION1) =item I<--email> Email the user if he/she has reached/exceeded threshold for quota. (OPTION2) =item I<--genmsg> Generate the default email template in /etc/quotawarn.msg file. (OPTION1) =head1 EXAMPLES Examples of some OPTIONS: B "quotadm -u tom" - will give a output like the following: UserName Usage(MB) Quota(MB) Usage(%) ThreshHold(%) Diff(+/-) tom 52.75 58.59 90.03% 90% 0.03%- B "quotadm -u tom --email" - will send an email to tom if his quota has reached or exceeded the threshold. B "quotadm --all-quota --email" - will send an email to each user whose quota has reached or exceeded the threshold. =head1 VARIABLES The following I in the script are configurable or must be configured in some systems: I<$msgfile> - Default: /etc/quotawarn.msg, this file contains the email that will be sent to the users whose quota has reached or exceeded $threshold. Inside this file you can use %user to mention the Username, %print to print the table of quota information, %quota to how much quota is assigned to the user. I<$mta> - Default: /usr/lib/sendmail, this is where you set the location of your MTA. Currently, this script only supports SENDMAIL and QMAIL. If you are using QMAIL, please enter the location of your qmail-inject. I<$echo> - Default: /bin/echo, this is the location of the echo command which is used to send mail for QMAIL. $threshold - Default: 90, this is the "high water mark" for the users. When user's disk usage equals/exceeds[>=] user's quota threshold, i.e. more than or equal to 90% of user's quota, then the script will send a warning message (/etc/quotawarn.msg) to the user. Actcually, the script will send the warning msg on every 2% increase after the quota of the user reaches his/her threshold if the user has not cleared his mail or freed up some disk space. =head1 README B is a user quota reporting tool. It can be used to get a table of users containing their quota usage, threshold limit, threshold usage etc. B can also be used to send e-mail warning messages to the users' whose quota has reached near or over quota I. =head1 REPORTING BUGS Please report bugs to or =head1 LICENSE I may be distributed under the same terms as Perl. =head1 PREREQUISITES Quota module for Perl - L =head1 OSNAMES Any =head1 SCRIPT CATEGORIES UNIX/System_administration =head1 AUTHOR Written by Ziaur Rahman , =head1 SEE ALSO quota(1), quotactl(2), fstab(5), edquota(8), quotacheck(8), quotaon(8), repquota(8), convertquota(8) =cut