summaryrefslogtreecommitdiff
path: root/parselog
blob: 0241071e1172b6b85890e0f1d0328ed78164b8e5 (plain)
  1. #!/usr/bin/perl -w
  2. #
  3. # parselog.pl v1.0.1
  4. #
  5. # Copyright (C)2000 Mark A. Bentley <bentlema@cs.umn.edu>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21. ###############################################################################
  22. #
  23. # This file was last modified: July 26, 2000
  24. #
  25. # You can download the latest distribution from my web site:
  26. #
  27. # http://www.cs.umn.edu/~bentlema/projects
  28. #
  29. # For comments, suggestions, bug reports, or whatever, you may contact me
  30. # via email:
  31. #
  32. # Mark A. Bentley <bentlema@cs.umn.edu>
  33. #
  34. ###############################################################################
  35. #
  36. #
  37. # DESCRIPTION
  38. #
  39. # This script is designed to accept log output from the Apache web server via
  40. # the CustomLog directive. It will create a directory for each virtual host's
  41. # logs, and will create a log file within this directory with the name based on
  42. # the year, month and day. When the day changes, yesturday's log files will be
  43. # closed, and new ones opened for today.
  44. #
  45. #
  46. # USAGE
  47. #
  48. # You will need to create a CustomLog entry in your httpd.conf in the global
  49. # section (not within a virtual host definition) like this:
  50. #
  51. # CustomLog "|/usr/local/bin/parselog" "[ %v %{%Y %m %d}t ] %h %l %u %t \"%r\" %s %b"
  52. #
  53. # The log formats definied within the brackets are absolutely necessary.
  54. # The %v will expand to the virtualhost name, and the %t (with its internal
  55. # format) will expand to the year, month, and day seperated by spaces. If you
  56. # change any of the values within these brackes, you will have to modify the
  57. # perl regular expression within the code below. The code will strip off these
  58. # brackets and everything within and write the remaining common log to the
  59. # appropriate directory and filename.
  60. #
  61. # This script will be fork/exec'ed with root perms if you've started apache as
  62. # root. To be safe you should specify the absolute path to parselog in your
  63. # CustomLog directive.
  64. #
  65. # You will also have to set the LOG_DIR in the configuration section below.
  66. #
  67. # This script will run with root privileges, so be careful if you decide to
  68. # make changes or add functionality.
  69. #
  70. #
  71. # Configuration
  72. #
  73. $LOG_DIR = "/var/log/apache-vhosts";
  74. $INPUT_SRC = STDIN; # you shouldn't need to change this.
  75. $LOG_FILE_PERMS = 0640;
  76. $LOG_FILE_OWNER = "root";
  77. $LOG_FILE_GROUP = "adm";
  78. $LOG_DIR_PERMS = 0755;
  79. $LOG_DIR_OWNER = "root";
  80. $LOG_DIR_GROUP = "root";
  81. $LOG_FILE_UID = ( getpwnam( $LOG_FILE_OWNER ))[2];
  82. $LOG_FILE_GID = ( getgrnam( $LOG_FILE_GROUP ))[2];
  83. $LOG_DIR_UID = ( getpwnam( $LOG_DIR_OWNER ))[2];
  84. $LOG_DIR_GID = ( getgrnam( $LOG_DIR_GROUP ))[2];
  85. #
  86. # Initialization
  87. #
  88. my %HOSTNAME = (); # hash of hostnames we've seen already
  89. my @OPEN_FH = (); # array of open filehandles for each hostname
  90. #
  91. # Support routines
  92. #
  93. sub flush { # Takes a filehandle
  94. local($old) = select(shift);
  95. $| = 1; print ""; $| = 0;
  96. select($old);
  97. }
  98. sub makenote { # Takes a string;
  99. $note = shift;
  100. $mylocaltime = localtime(time());
  101. print STDERR "[$mylocaltime] $0: ", $note, "\n";
  102. }
  103. #
  104. # Main loop
  105. #
  106. makenote("Starting up... PID: $$");
  107. makenote("INPUT_SRC = $INPUT_SRC");
  108. if ( -d $LOG_DIR ) {
  109. makenote("LOG_DIR = $LOG_DIR");
  110. } else {
  111. makenote("Fatal Error: $LOG_DIR does not exist!");
  112. exit( 1 );
  113. }
  114. makenote("Log Directory: " .
  115. "$LOG_DIR_OWNER($LOG_DIR_UID) " .
  116. "$LOG_DIR_GROUP($LOG_DIR_GID) $LOG_DIR_PERMS");
  117. makenote("Log Files: " .
  118. "$LOG_FILE_OWNER($LOG_FILE_UID) " .
  119. "$LOG_FILE_GROUP($LOG_FILE_GID) $LOG_FILE_PERMS");
  120. $previous_day = "0";
  121. while( <$INPUT_SRC> ) {
  122. m/^\[ (\S+) (\d+) (\d+) (\d+) \] (.*)/; # parse the log input here
  123. $log_hostname = $1;
  124. $log_year = $2;
  125. $log_month = $3;
  126. $log_day = $4;
  127. $log_common = $5;
  128. $log_pathname = "$LOG_DIR/$log_hostname";
  129. #
  130. # Did the day change?
  131. #
  132. if ( $log_day ne $previous_day ) {
  133. makenote("Day change.");
  134. %HOSTNAME = ();
  135. makenote("HOSTNAME hash reset.");
  136. makenote("OPEN_FH: $#OPEN_FH");
  137. if ( $#OPEN_FH > 0 ) {
  138. foreach $fh ( @OPEN_FH ) {
  139. makenote("Closing $fh filehandle.");
  140. close( $fh );
  141. }
  142. }
  143. @OPEN_FH = ();
  144. makenote("OPEN_FH array reset.");
  145. }
  146. #
  147. # Have we seen this virtual host today?
  148. #
  149. if ( ! $HOSTNAME{$log_hostname} ) {
  150. $HOSTNAME{$log_hostname} = 1; # mark host as seen
  151. #
  152. # create hostname directory within LOG_DIR
  153. #
  154. if ( ! -e $log_pathname ) {
  155. makenote("mkdir: $log_pathname");
  156. mkdir( $log_pathname, $LOG_DIR_PERMS );
  157. chown( $LOG_DIR_UID, $LOG_DIR_GID, $log_pathname );
  158. chmod( $LOG_DIR_PERMS, $log_pathname );
  159. }
  160. #
  161. # open logfile named year.month.day for appending
  162. # using $log_hostname as the filehandle name
  163. #
  164. my $current_log = "$log_pathname/$log_year.$log_month.$log_day";
  165. makenote("open: $current_log");
  166. open( $log_hostname, ">> $current_log");
  167. chown( $LOG_FILE_UID, $LOG_FILE_GID, "$current_log" );
  168. chmod( $LOG_FILE_PERMS, "$current_log" );
  169. #
  170. # maintain a list of open filehandles
  171. #
  172. push @OPEN_FH, $log_hostname;
  173. }
  174. #
  175. # Write the log line to the appropriate log file. (Remember that
  176. # the file handle name is the same as the hostname.)
  177. #
  178. print $log_hostname $log_common, "\n";
  179. flush( $log_hostname );
  180. $previous_day = $log_day;
  181. }