Subversion Repositories sysadmin_scripts

Rev

Rev 146 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
146 rodolico 1
#! /usr/bin/env perl
2
 
3
# Copyright (c) 2024, Daily Data, Inc
4
#
5
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following 
6
# conditions are met:
7
#
8
#  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
#  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
10
# disclaimer in the documentation and/or other materials provided with the distribution.
11
#
12
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
13
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
14
# SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
16
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
17
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.[12] 
18
#
19
# Description
20
# Script to clean up security log tables on WordPress sites
21
# Some wordpress site security suites continously add logs, but do not offer the ability to clean up entries after
22
# a certain period of time. This can cause database tables to grow without relief until they threaten to fill
23
# the database partition
24
# This came to light recently when the half dozen WordPress sites we manage threatened to fill the database partition
25
# after a few years of monitoring.
26
#
27
# Before we ran this script, the 6G partition was 81% full, and after cleaning up, that dropped to 52%, so almost a 
28
# third of the database size was years of logs, or almost 2G. Of course, you can increase the disk space available on
29
# the partition, but we just wanted to keep 4 weeks of logs
30
#
31
# Designed to be run from a monthly or weekly cron job, it will look for all MySQL databases, then check each one in turn
32
# for the existence of the security log tables. If a database contains the tables, it will run the script to remove
33
# anything over $KEEPDAYS days old.
34
#
35
# this is a quick script and has only been tested on one single system, where the root user had access to all MySQL
36
# functions without password. Modifications will need to be made on systems which are more secure.
147 rodolico 37
#
38
# This script is available via subversion at
39
# svn co http://svn.dailydata.net/svn/sysadmin_scripts/trunk/Wordpress/cleanWPSecLogs
40
# NOTE: the above repository is a working copy from Daily Data, which can be modified as required without notification
146 rodolico 41
 
42
 
43
use strict;
44
use warnings;
45
 
46
my $KEEPDAYS = 28;
47
 
48
# clean up the output from mysqlshow
49
# if the name does not match the regular expression
50
# return null, else return the matched code
51
sub clean {
52
   my $name = shift;
53
   # regex matches any database beginning with c## for our ISPConfig setup
54
   # pretty sloppy regex, but works on our system
55
   $name =~ m/(c\d+[a-z0-9_]+)/i;
56
   return $1 ? $1 : '';;
57
}
58
 
59
# create a temporary sql file which is sent to all valid databases
60
# NOTE: it is the responsiblity of the script to remove the temp file (we don't do it here)
61
sub createSQL {
62
   use File::Temp;
63
   my $fh = File::Temp->new( SUFFIX => '.sql', UNLINK => 0, TEMPLATE=> '/tmp/cleanLogs.XXXXXXXXXX' );
64
   # NOTE: if you don't want any logs kept, you can use 'truncate wp_itsec_logs' instead, which is faster and also 
65
   # recovers disk space
66
   # delete anything older over $KEEPDAYS old from wp_itsec_logs. timestamp appears to be UT, so will be off by some
67
   print $fh "DELETE FROM wp_itsec_logs WHERE timestamp <DATE_SUB(NOW(), INTERVAL $KEEPDAYS DAY);\n";
68
   # same with wp_itsec_lockouts
69
   print $fh "delete FROM wp_itsec_lockouts WHERE lockout_expire < DATE_SUB(NOW(), INTERVAL $KEEPDAYS DAY);\n";
70
   # next two commands recover disk space from tables. You can ignore this after the first run as very little will remain
71
   # between sessions
72
   print $fh "optimize table wp_itsec_logs;\n";
73
   print $fh "optimize table wp_itsec_lockouts;\n";
74
   close $fh;
75
   return $fh->filename; # returns the name of the temp file
76
}
77
 
78
my $sqlFile = &createSQL(); # makes the sql file to be run on each database
79
# print "$sqlFile\n";
80
 
81
# simple way to get list of all databases, but they need to be cleaned up afterwards
82
my @tables = `mysqlshow`;
83
for ( my $i = 0; $i < @tables; $i++ ) {
84
   $tables[$i] = &clean( $tables[$i] );
85
}
86
#die join( "\n", @tables ) . "\n";
87
 
88
# process each table
89
for ( my $table = 0; $table < @tables ; $table++ ) {
90
   next unless $tables[$table]; # skip anything that &clean zapped
91
   # command passed to mysql to determine if the table wp_itsec_logs exists in database
92
   my $command = "echo show tables like \\'wp_itsec_logs\\' | mysql $tables[$table]";
93
   #die "$command\n";
94
   my $valid = `$command`; # if $command has something, it is valid. If it is the empty string, no table, so not valid
95
   #die "'$valid'\n";
96
   if ( $valid ) {
97
      print "Found in $tables[$table]\n";
98
      print `mysql $tables[$table] < $sqlFile`; # run mysql against database passing the commands from the temp file in
99
   }
100
}
101
# remove the temp file
102
unlink( $sqlFile ) or die "Could not delete temp file $sqlFile\n";
103
1;