#!/usr/bin/perl # # You will be able to download the latest version of this script at: # http://mzrahman.com/codes/quotadm # # 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. # Thanks to Olivier Bekoin for feedback. #--------Version 0.0.2c------------------------------------------------------------------------------- # 22-04-03 Z - Fixed a bug in the email sending subroutine. # BUG: Resetting the marker for email to zero (0). # - Added the Version and Author info. in the usage subroutine. # - Added some more examples in the usage subroutine. # - Changed the behavior of sending email on every 2% increase. Now, # the script will send only one message once when the quota exceeds # the threshold. #--------Version 0.0.2d------------------------------------------------------------------------------- # 06-05-03 Z - Fixed some textual imressions. # - Added the link to the enablequota.sh. # (http://mzrahman.com/codes/bash/enablequota.tar) # #--------Version 0.0.2e------------------------------------------------------------------------------- # 07-08-03 Z - Added the feature for sending summary email to administrator. # [Although, it was in my TODO list, but thanks to Paul Denyer for his # request or I would take ages to do this :)] # - No need to send email when the user's quota is full as email will # bounce anyways. Fixed. # - Fixed some "not initialized" variables. # - Modified the generatemsg() function to generate the quotawarnadmin.msg. # # # Author: Ziaur Rahman # # Synopsis: # # File quotadm # # Program Name Quota Administration (QUOTA ADMinistration). # # Version 0.0.2e # # 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 $msgfileuser - Default: /etc/quotawarnuser.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, %table to print the # table of quota information, %quota to how much quota is assigned to the user. # # $msgfileadmin - Default: /etc/quotawarnadmin.msg, this file contains the email # that will be sent to the admin summarising all the users that have exceeded # their threshold. # # $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/quotawarnuser.msg) to the user. The script will send the warning # only once. # # $sendadmin - If value is 1, then the script will send summary email to admin. # If value is 0, then the script will not send the summary email. # # $adminemail - Email address for administrator. The '@' should be preceeded with # '\', so email address should look like: admin\@domain.com # # Disclaimer I take no responsibility for this scripts actions should you choose to # install/use it. Should you find it useful, though, I'd appreciate it if you'd # leave the copyright/origination comments in place. ########################################################################################################## $VERSION = "0.0.2e"; # # Configurable Global variables start here... # # Define the global variables here $msgfileuser = "/etc/quotawarnuser.msg"; $msgfileadmin = "/etc/quotawarnadmin.msg"; $mta = "/usr/lib/sendmail"; # define your MTA location here. For Qmail, you should set the path for qmail-inject $echo = "/bin/echo"; $threshold = 90; $sendadmin = 0; # set to 0 if you don't want a summary to be sent to the admin. $adminemail = "admin\@domain.com"; # please change this to your address, carefull about the '\@'. # # Configurable Global variables end here... # # # A quick check on the Global Variables Default values # if ($sendadmin) { if ($adminemail =~ "domain.com") { print "\n"; print "Please change the email address for administrator (\$adminemail) which is set to $adminemail\n"; print "Or, if you don't want the summary to be sent to the administrator then\n"; print "please change the value for the variable \$sendadmin to 0\n"; print "\n"; exit; } } # 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 "\n\n\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"; print "\tYou can use the following automated BASH script to enable quota in your system:\n"; print "\t\thttp://mzrahman.com/codes/bash/enablequota.tar\n"; print "\n\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,$printtab,$quotaa,$who) = @_; my $msg = ""; $quotadec = sprintf("%0.2d",$quotaa); if ($who eq "admin") { open (MSGFILE, "$msgfileadmin") or die "can not open $msgfileadmin\n"; } elsif ($who eq "user") { open (MSGFILE, "$msgfileuser") or die "can not open $msgfileuser\n"; } while () { $line = $_; $line =~ s/%user/$user/; $line =~ s/%table/$printtab/; $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,"%","+"); } $wsent = 0; if (-e("$gcos/.quotawarn")) { open (QW,"+<$gcos/.quotawarn"); while () { chomp($wsent = $_); } } if ($percentUsage >= $threshold) { 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); $printemadm .= sprintf ("%0s%15.2f%15.2f%15s%15s%15s\n",$user,$usageinMB,$quotainMB,$perUsage,$thresholds,$diffthresh); if ((!$wsent) && ($percentUsage < 100)) { # There is no need to send email to a user whose Quota is full. 'Cause, email will not go anyways. &sendemail($user,$printem,$quotainMB,"user"); open (QW,">$gcos/.quotawarn"); print QW "1"; } $sendemailadm = 1 if $sendadmin; } } else { if (-e("$gcos/.quotawarn")) { open (QW,">$gcos/.quotawarn"); print QW "0"; } } 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; if ($sendemailadm) { &sendemail($adminemail,$printemadm,$quotainMB,"admin"); } } sub generatemsg { if (-e "/etc/quotawarnuser.msg") { BACKYN: print "/etc/quotawarnuser.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/quotawarnuser.msg") or die "Can't create file /etc/quotawarnuser.msg.\n"; } elsif (($yn eq "N") || ($yn eq "n")) { print "\nYou chose not to overwrite the file /etc/quotawarnuser.msg.\n"; print "Please backup your data in the file /etc/quotawarnuser.msg and try again.\n"; exit; } else { goto BACKYN; } } else { open(GENMSG,">/etc/quotawarnuser.msg") or die "Can't create file /etc/quotawarnuser.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: %table GENEOF print "\nThe file /etc/quotawarnuser.msg is generated.\n"; print "Please edit the From: and To: field to add your domain name.\n"; print "Also you can use %user to mention the Username, %table to print the table of quota information,\n"; print "and %quota to how much quota is assigned to the user.\n\n"; if (-e "/etc/quotawarnadmin.msg") { BACKYN: print "/etc/quotawarnadmin.msg file exists!\n"; print "Do you want to overwrite it? (Y/N): "; chomp($yn = ); if (($yn eq "Y") || ($yn eq "y")) { open(GENAMSG,">/etc/quotawarnadmin.msg") or die "Can't create file /etc/quotawarnadmin.msg.\n"; } elsif (($yn eq "N") || ($yn eq "n")) { print "\nYou chose not to overwrite the file /etc/quotawarnadmin.msg.\n"; print "Please backup your data in the file /etc/quotawarnadmin.msg and try again.\n"; exit; } else { goto BACKYN; } } else { open(GENAMSG,">/etc/quotawarnadmin.msg") or die "Can't create file /etc/quotawarnadmin.msg.\n"; } print GENAMSG << 'GENAEOF'; From: "Quota Administrator" <%user> To: %user Subject: Summary of Users' Quota whose threshold has exceeded. Please mark that no warning email has been sent to those users whose usage is 100% of their quota. The email would bounce as those users are already over quota. ----------------------------- Summary of Quota Usage ------------------------------ UserName Usage(MB) Quota(MB) Usage(%) ThreshHold(%) Diff(+/-) %table GENAEOF print "\nThe file /etc/quotawarnadmin.msg is generated.\n"; } sub usage { print "\nQuotadm, Version: $VERSION"; print "\nAuthor: Ziaur Rahman \n"; 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/quotawarnuser.msg and /etc/quotawarnadmin.msg file. (OPTION1)\n"; print "\n"; print "Examples:\n\n"; print "Example 1: \n\"quotadm -u tom\" \n- will show tom's quota information.\n\n"; print "Example 2: \n\"quotadm --all-quota\" \n- will show all quota enabled users' quota information.\n\n"; print "Example 3: \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 4: \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/quotawarnuser.msg and /etc/quotawarnadmin.msg files. (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/quotawarnuser.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, %table to print the table of quota information, %quota to how much quota is assigned to the user. I<$msgfileadmin> - Default: /etc/quotawarnadmin.msg, this file contains the email that will be sent to the admin summarising all the users that have exceeded their threshold. 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. I<$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/quotawarnuser.msg) to the user. The message will be sent to user only once. I<$sendadmin> - If value is 1, then the script will send summary email to admin. If value is 0, then the script will not send the summary email. I<$adminemail> - Email address for administrator. The '@' should be preceeded with '\', so email address should look like: admin\@domain.com =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 FILES B 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, %table to print the table of quota information, %quota to how much quota is assigned to the user. B This file contains the email that will be sent to the admin summarising all the users that have exceeded their threshold. =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