re-mqueue.pl
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:9k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. #!/usr/bin/perl
  2. #
  3. # re-mqueue -- requeue messages from queueA to queueB based on age.
  4. #
  5. # Contributed by Paul Pomes <ppomes@Qualcomm.COM>.
  6. # http://www.qualcomm.com/~ppomes/
  7. #
  8. # Usage: re-mqueue [-d] queueA queueB seconds
  9. #
  10. #  -d enable debugging
  11. #  queueA source directory
  12. #  queueB destination directory
  13. #  seconds select files older than this number of seconds 
  14. #
  15. # Example: re-mqueue /var/spool/mqueue /var/spool/mqueue2 2700
  16. #
  17. # Moves the qf* and df* files for a message from /var/spool/mqueue to
  18. # /var/spool/mqueue2 if the df* file is over 2700 seconds old.
  19. #
  20. # The qf* file can't be used for age checking as it's partially re-written
  21. # with the results of the last queue run.
  22. #
  23. # Rationale: With a limited number of sendmail processes allowed to run,
  24. # messages that can't be delivered immediately slow down the ones that can.
  25. # This becomes especially important when messages are being queued instead
  26. # of delivered right away, or when the queue becomes excessively deep.
  27. # By putting messages that have already failed one or more delivery attempts
  28. # into another queue, the primary queue can be kept small and fast.
  29. #
  30. # On postoffice.cso.uiuc.edu, the primary sendmail daemon runs the queue
  31. # every thirty minutes.  Messages over 45 minutues old are moved to
  32. # /var/spool/mqueue2 where sendmail runs every hour.  Messages more than
  33. # 3.25 hours old are moved to /var/spool/mqueue3 where sendmail runs every
  34. # four hours.  Messages more than a day old are moved to /var/spool/mqueue4
  35. # where sendmail runs three times a day.  The idea is that a message is
  36. # tried at least twice in the first three queues before being moved to the
  37. # old-age ghetto.
  38. #
  39. # (Each must be re-formed into a single line before using in crontab)
  40. #
  41. # 08 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue ## /var/spool/mqueue2 2700
  42. # 11 * * * * /usr/lib/sendmail -oQ/var/spool/mqueue2 -q > ## > /var/log/mqueue2 2>&1
  43. # 38 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue2
  44. # /var/spool/mqueue3 11700
  45. # 41 1,5,9,13,17,21 * * * /usr/lib/sendmail -oQ/var/spool/mqueue3 -q ## > /var/log/mqueue3 2>&1
  46. # 48 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue3
  47. # /var/spool/mqueue4 100000
  48. #53 3,11,19 * * * /usr/lib/sendmail -oQ/var/spool/mqueue4 -q > ## > /var/log/mqueue4 2>&1
  49. #
  50. #
  51. # N.B., the moves are done with link().  This has two effects: 1) the mqueue*
  52. # directories must all be on the same filesystem, and 2) the file modification
  53. # times are not changed.  All times must be cumulative from when the df*
  54. # file was created.
  55. #
  56. # Copyright (c) 1995 University of Illinois Board of Trustees and Paul Pomes
  57. # All rights reserved.
  58. #
  59. # Redistribution and use in source and binary forms, with or without
  60. # modification, are permitted provided that the following conditions
  61. # are met:
  62. # 1. Redistributions of source code must retain the above copyright
  63. #    notice, this list of conditions and the following disclaimer.
  64. # 2. Redistributions in binary form must reproduce the above copyright
  65. #    notice, this list of conditions and the following disclaimer in the
  66. #    documentation and/or other materials provided with the distribution.
  67. # 3. All advertising materials mentioning features or use of this software
  68. #    must display the following acknowledgement:
  69. #       This product includes software developed by the University of
  70. #       Illinois at Urbana and their contributors.
  71. # 4. Neither the name of the University nor the names of their contributors
  72. #    may be used to endorse or promote products derived from this software
  73. #    without specific prior written permission.
  74. #
  75. # THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND
  76. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  77. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  78. # ARE DISCLAIMED.  IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE
  79. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  80. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  81. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  82. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  83. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  84. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  85. # SUCH DAMAGE.
  86. #
  87. # @(#)$OrigId: re-mqueue,v 1.3 1995/05/25 18:14:53 p-pomes Exp $
  88. #
  89. # Updated by Graeme Hewson <ghewson@uk.oracle.com> May 1999
  90. #
  91. # 'use Sys::Syslog' for Perl 5
  92. # Move transcript (xf) files if they exist
  93. # Allow zero-length df files (empty message body)
  94. # Preserve $! for error messages
  95. #
  96. use Sys::Syslog;
  97. $LOCK_EX = 2;
  98. $LOCK_NB = 4;
  99. $LOCK_UN = 8;
  100. # Count arguments, exit if wrong in any way.
  101. die "Usage: $0 [-d] queueA queueB secondsn" if ($#ARGV < 2);
  102. while ($_ = $ARGV[0], /^-/) {
  103.     shift;
  104.     last if /^--$/;
  105.     /^-d/ && $debug++;
  106. }
  107. $queueA = shift;
  108. $queueB = shift;
  109. $age = shift;
  110. die "$0: $queueA not a directoryn" if (! -d $queueA);
  111. die "$0: $queueB not a directoryn" if (! -d $queueB);
  112. die "$0: $age isn't a valid number of seconds for agen" if ($age =~ /D/);
  113. # chdir to $queueA and read the directory.  When a df* file is found, stat it.
  114. # If it's older than $age, lock the corresponding qf* file.  If the lock
  115. # fails, give up and move on.  Once the lock is obtained, verify that files
  116. # of the same name *don't* already exist in $queueB and move on if they do.
  117. # Otherwise re-link the qf* and df* files into $queueB then release the lock.
  118. chdir "$queueA" || die "$0: can't cd to $queueA: $!n";
  119. opendir (QA, ".") || die "$0: can't open directory $queueA for reading: $!n";
  120. @dfiles = grep(/^df/, readdir(QA));
  121. $now = time();
  122. ($program = $0) =~ s,.*/,,;
  123. &openlog($program, 'pid', 'mail');
  124. # Loop through the dfiles
  125. while ($dfile = pop(@dfiles)) {
  126.     print "Checking $dfilen" if ($debug);
  127.     ($qfile = $dfile) =~ s/^d/q/;
  128.     ($xfile = $dfile) =~ s/^d/x/;
  129.     ($mfile = $dfile) =~ s/^df//;
  130.     if (! -e $dfile) {
  131. print "$dfile is gone - skippingn" if ($debug);
  132. next;
  133.     }
  134.     if (! -e $qfile || -z $qfile) {
  135. print "$qfile is gone or zero bytes - skippingn" if ($debug);
  136. next;
  137.     }
  138.     $mtime = $now;
  139.     ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
  140.      $atime,$mtime,$ctime,$blksize,$blocks) = stat($dfile);
  141.     # Compare timestamps
  142.     if (($mtime + $age) > $now) {
  143. printf ("%s is %d seconds old - skippingn", $dfile, $now-$mtime) if ($debug);
  144. next;
  145.     }
  146.     # See if files of the same name already exist in $queueB
  147.     if (-e "$queueB/$dfile") {
  148. print "$queueb/$dfile already exists - skippingn" if ($debug);
  149. next;
  150.     }
  151.     if (-e "$queueB/$qfile") {
  152. print "$queueb/$qfile already exists - skippingn" if ($debug);
  153. next;
  154.     }
  155.     if (-e "$queueB/$xfile") {
  156. print "$queueb/$xfile already exists - skippingn" if ($debug);
  157. next;
  158.     }
  159.     # Try and lock qf* file
  160.     unless (open(QF, ">>$qfile")) {
  161. print "$qfile: $!n" if ($debug);
  162. next;
  163.     }
  164.     $retval = flock(QF, $LOCK_EX|$LOCK_NB) || ($retval = -1);
  165.     if ($retval == -1) {
  166. print "$qfile already flock()ed - skippingn" if ($debug);
  167. close(QF);
  168. next;
  169.     }
  170.     print "$qfile now flock()edn" if ($debug);
  171.     # Show time!  Do the link()s
  172.     if (link("$dfile", "$queueB/$dfile") == 0) {
  173. $bang = $!;
  174. &syslog('err', 'link(%s, %s/%s): %s', $dfile, $queueB, $dfile, $bang);
  175. print STDERR "$0: link($dfile, $queueB/$dfile): $bangn";
  176. exit (1);
  177.     }
  178.     if (link("$qfile", "$queueB/$qfile") == 0) {
  179. $bang = $!;
  180. &syslog('err', 'link(%s, %s/%s): %s', $qfile, $queueB, $qfile, $bang);
  181. print STDERR "$0: link($qfile, $queueB/$qfile): $bangn";
  182. unlink("$queueB/$dfile");
  183. exit (1);
  184.     }
  185.     if (-e "$xfile") {
  186. if (link("$xfile", "$queueB/$xfile") == 0) {
  187.     $bang = $!;
  188.     &syslog('err', 'link(%s, %s/%s): %s', $xfile, $queueB, $xfile, $bang);
  189.     print STDERR "$0: link($xfile, $queueB/$xfile): $bangn";
  190.     unlink("$queueB/$dfile");
  191.     unlink("$queueB/$qfile");
  192.     exit (1);
  193. }
  194.     }
  195.     # Links created successfully.  Unlink the original files, release the
  196.     # lock, and close the file.
  197.     print "links okn" if ($debug);
  198.     if (unlink($qfile) == 0) {
  199. $bang = $!;
  200. &syslog('err', 'unlink(%s): %s', $qfile, $bang);
  201. print STDERR "$0: unlink($qfile): $bangn";
  202. exit (1);
  203.     }
  204.     if (unlink($dfile) == 0) {
  205. $bang = $!;
  206. &syslog('err', 'unlink(%s): %s', $dfile, $bang);
  207. print STDERR "$0: unlink($dfile): $bangn";
  208. exit (1);
  209.     }
  210.     if (-e "$xfile") {
  211. if (unlink($xfile) == 0) {
  212.     $bang = $!;
  213.     &syslog('err', 'unlink(%s): %s', $xfile, $bang);
  214.     print STDERR "$0: unlink($xfile): $bangn";
  215.     exit (1);
  216. }
  217.     }
  218.     flock(QF, $LOCK_UN);
  219.     close(QF);
  220.     &syslog('info', '%s moved to %s', $mfile, $queueB);
  221.     print "Done with $dfile $qfilenn" if ($debug);
  222. }
  223. exit 0;