commit | author | age
|
5de2af
|
1 |
<?php |
M |
2 |
|
|
3 |
/* |
|
4 |
Copyright (c) 2013, Marius Cramer, pixcept KG |
|
5 |
All rights reserved. |
|
6 |
|
|
7 |
Redistribution and use in source and binary forms, with or without modification, |
|
8 |
are permitted provided that the following conditions are met: |
|
9 |
|
|
10 |
* Redistributions of source code must retain the above copyright notice, |
|
11 |
this list of conditions and the following disclaimer. |
|
12 |
* Redistributions in binary form must reproduce the above copyright notice, |
|
13 |
this list of conditions and the following disclaimer in the documentation |
|
14 |
and/or other materials provided with the distribution. |
|
15 |
* Neither the name of ISPConfig nor the names of its contributors |
|
16 |
may be used to endorse or promote products derived from this software without |
|
17 |
specific prior written permission. |
|
18 |
|
|
19 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
20 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
21 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
22 |
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
|
23 |
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
24 |
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
25 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
|
26 |
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
27 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
|
28 |
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
29 |
*/ |
|
30 |
|
|
31 |
class cronjob_logfiles extends cronjob { |
|
32 |
|
b1a6a5
|
33 |
// job schedule |
MC |
34 |
protected $_schedule = '0 0 * * *'; |
5de2af
|
35 |
|
b1a6a5
|
36 |
/* this function is optional if it contains no custom code */ |
MC |
37 |
public function onPrepare() { |
|
38 |
global $app; |
5de2af
|
39 |
|
b1a6a5
|
40 |
parent::onPrepare(); |
MC |
41 |
} |
5de2af
|
42 |
|
b1a6a5
|
43 |
/* this function is optional if it contains no custom code */ |
MC |
44 |
public function onBeforeRun() { |
|
45 |
global $app; |
5de2af
|
46 |
|
b1a6a5
|
47 |
return parent::onBeforeRun(); |
MC |
48 |
} |
5de2af
|
49 |
|
b1a6a5
|
50 |
public function onRunJob() { |
MC |
51 |
global $app, $conf; |
5de2af
|
52 |
|
b1a6a5
|
53 |
//###################################################################################################### |
MC |
54 |
// Make the web logfiles directories world readable to enable ftp access |
|
55 |
//###################################################################################################### |
5de2af
|
56 |
|
b1a6a5
|
57 |
if(is_dir('/var/log/ispconfig/httpd')) exec('chmod +r /var/log/ispconfig/httpd/*'); |
5de2af
|
58 |
|
b1a6a5
|
59 |
//###################################################################################################### |
MC |
60 |
// Manage and compress web logfiles and create traffic statistics |
|
61 |
//###################################################################################################### |
5de2af
|
62 |
|
a6e3ae
|
63 |
$sql = "SELECT domain_id, domain, type, document_root, web_folder, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain' or type = 'vhostalias') AND server_id = ?"; |
MC |
64 |
$records = $app->db->queryAllRecords($sql, $conf['server_id']); |
b1a6a5
|
65 |
foreach($records as $rec) { |
5de2af
|
66 |
|
b1a6a5
|
67 |
//* create traffic statistics based on yesterdays access log file |
MC |
68 |
$yesterday = date('Ymd', time() - 86400); |
5de2af
|
69 |
|
b1a6a5
|
70 |
$log_folder = 'log'; |
511ba5
|
71 |
if($rec['type'] == 'vhostsubdomain' || $rec['type'] == 'vhostalias') { |
cc7a82
|
72 |
$tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = ?', $rec['parent_domain_id']); |
b1a6a5
|
73 |
$subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']); |
MC |
74 |
if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id']; |
|
75 |
$log_folder .= '/' . $subdomain_host; |
|
76 |
unset($tmp); |
|
77 |
} |
5de2af
|
78 |
|
b1a6a5
|
79 |
$logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log'; |
MC |
80 |
$total_bytes = 0; |
5de2af
|
81 |
|
b1a6a5
|
82 |
$handle = @fopen($logfile, "r"); |
MC |
83 |
if ($handle) { |
|
84 |
while (($line = fgets($handle, 4096)) !== false) { |
|
85 |
if (preg_match('/^\S+ \S+ \S+ \[.*?\] "\S+.*?" \d+ (\d+) ".*?" ".*?"/', $line, $m)) { |
|
86 |
$total_bytes += intval($m[1]); |
|
87 |
} |
|
88 |
} |
5de2af
|
89 |
|
b1a6a5
|
90 |
//* Insert / update traffic in master database |
MC |
91 |
$traffic_date = date('Y-m-d', time() - 86400); |
cc7a82
|
92 |
$tmp = $app->dbmaster->queryOneRecord("select hostname from web_traffic where hostname=? and traffic_date=?", $rec['domain'], $traffic_date); |
b1a6a5
|
93 |
if(is_array($tmp) && count($tmp) > 0) { |
cc7a82
|
94 |
$sql = "UPDATE web_traffic SET traffic_bytes=traffic_bytes + ? WHERE hostname = ? AND traffic_date = ?"; |
MC |
95 |
$app->dbmaster->query($sql, $total_bytes, $rec['domain'], $traffic_date); |
b1a6a5
|
96 |
} else { |
cc7a82
|
97 |
$sql = "INSERT INTO web_traffic (hostname, traffic_date, traffic_bytes) VALUES (?, ?, ?)"; |
MC |
98 |
$app->dbmaster->query($sql, $rec['domain'], $traffic_date, $total_bytes); |
b1a6a5
|
99 |
} |
5de2af
|
100 |
|
b1a6a5
|
101 |
fclose($handle); |
MC |
102 |
} |
5de2af
|
103 |
|
b1a6a5
|
104 |
$yesterday2 = date('Ymd', time() - 86400*2); |
MC |
105 |
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday2.'-access.log'); |
5de2af
|
106 |
|
b1a6a5
|
107 |
//* Compress logfile |
MC |
108 |
if(@is_file($logfile)) { |
|
109 |
// Compress yesterdays logfile |
|
110 |
exec("gzip -c $logfile > $logfile.gz"); |
|
111 |
unlink($logfile); |
|
112 |
} |
da0a81
|
113 |
|
MC |
114 |
$cron_logfiles = array('cron.log', 'cron_error.log', 'cron_wget.log'); |
|
115 |
foreach($cron_logfiles as $cron_logfile) { |
|
116 |
$cron_logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/' . $cron_logfile); |
|
117 |
|
|
118 |
// rename older files (move up by one) |
|
119 |
$num = 7; |
|
120 |
while($num >= 1 && is_file($cron_logfile . '.' . $num . '.gz')) { |
|
121 |
rename($cron_logfile . '.' . $num . '.gz', $cron_logfile . '.' . ($num + 1) . '.gz'); |
|
122 |
$num--; |
|
123 |
} |
|
124 |
|
|
125 |
// compress current logfile |
b41dfd
|
126 |
if(is_file($cron_logfile)) { |
da0a81
|
127 |
exec("gzip -c $cron_logfile > $cron_logfile.1.gz"); |
MC |
128 |
exec("cat /dev/null > $cron_logfile"); |
|
129 |
} |
|
130 |
// remove older logs |
|
131 |
$num = 7; |
|
132 |
while(is_file($cron_logfile . '.' . $num . '.gz')) { |
|
133 |
@unlink($cron_logfile . '.' . $num . '.gz'); |
|
134 |
$num++; |
|
135 |
} |
|
136 |
} |
5de2af
|
137 |
|
b1a6a5
|
138 |
// rotate and compress the error.log when it exceeds a size of 10 MB |
MC |
139 |
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/error.log'); |
|
140 |
if(is_file($logfile) && filesize($logfile) > 10000000) { |
|
141 |
exec("gzip -c $logfile > $logfile.1.gz"); |
|
142 |
exec("cat /dev/null > $logfile"); |
|
143 |
} |
5de2af
|
144 |
|
b1a6a5
|
145 |
// delete logfiles after 30 days |
MC |
146 |
$month_ago = date('Ymd', time() - 86400 * 30); |
|
147 |
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$month_ago.'-access.log.gz'); |
|
148 |
if(@is_file($logfile)) { |
|
149 |
unlink($logfile); |
|
150 |
} |
5de2af
|
151 |
|
b1a6a5
|
152 |
//* Delete older Log files, in case that we missed them before due to serverdowntimes. |
MC |
153 |
$datepart = date('Ym', time() - 86400 * 31 * 2); |
5de2af
|
154 |
|
b1a6a5
|
155 |
$logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log.gz'; |
MC |
156 |
exec('rm -f '.$logfile); |
5de2af
|
157 |
|
b1a6a5
|
158 |
$logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log'; |
MC |
159 |
exec('rm -f '.$logfile); |
|
160 |
} |
5de2af
|
161 |
|
b1a6a5
|
162 |
//* Delete old logfiles in /var/log/ispconfig/httpd/ that were created by vlogger for the hostname of the server |
MC |
163 |
exec('hostname -f', $tmp_hostname); |
|
164 |
if($tmp_hostname[0] != '' && is_dir('/var/log/ispconfig/httpd/'.$tmp_hostname[0])) { |
|
165 |
exec('cd /var/log/ispconfig/httpd/'.$tmp_hostname[0]."; find . -mtime +30 -name '*.log' | xargs rm > /dev/null 2> /dev/null"); |
|
166 |
} |
|
167 |
unset($tmp_hostname); |
5de2af
|
168 |
|
b1a6a5
|
169 |
//###################################################################################################### |
MC |
170 |
// Rotate the ispconfig.log file |
|
171 |
//###################################################################################################### |
5de2af
|
172 |
|
b1a6a5
|
173 |
// rotate the ispconfig.log when it exceeds a size of 10 MB |
MC |
174 |
$logfile = $conf['ispconfig_log_dir'].'/ispconfig.log'; |
|
175 |
if(is_file($logfile) && filesize($logfile) > 10000000) { |
|
176 |
exec("gzip -c $logfile > $logfile.1.gz"); |
|
177 |
exec("cat /dev/null > $logfile"); |
|
178 |
} |
|
179 |
|
|
180 |
// rotate the cron.log when it exceeds a size of 10 MB |
|
181 |
$logfile = $conf['ispconfig_log_dir'].'/cron.log'; |
|
182 |
if(is_file($logfile) && filesize($logfile) > 10000000) { |
|
183 |
exec("gzip -c $logfile > $logfile.1.gz"); |
|
184 |
exec("cat /dev/null > $logfile"); |
|
185 |
} |
|
186 |
|
|
187 |
// rotate the auth.log when it exceeds a size of 10 MB |
|
188 |
$logfile = $conf['ispconfig_log_dir'].'/auth.log'; |
|
189 |
if(is_file($logfile) && filesize($logfile) > 10000000) { |
|
190 |
exec("gzip -c $logfile > $logfile.1.gz"); |
|
191 |
exec("cat /dev/null > $logfile"); |
|
192 |
} |
|
193 |
|
|
194 |
//###################################################################################################### |
|
195 |
// Cleanup website tmp directories |
|
196 |
//###################################################################################################### |
|
197 |
|
cc7a82
|
198 |
$sql = "SELECT domain_id, domain, document_root, system_user FROM web_domain WHERE server_id = ?"; |
MC |
199 |
$records = $app->db->queryAllRecords($sql, $conf['server_id']); |
b1a6a5
|
200 |
$app->uses('system'); |
MC |
201 |
if(is_array($records)) { |
|
202 |
foreach($records as $rec){ |
|
203 |
$tmp_path = realpath(escapeshellcmd($rec['document_root'].'/tmp')); |
|
204 |
if($tmp_path != '' && strlen($tmp_path) > 10 && is_dir($tmp_path) && $app->system->is_user($rec['system_user'])){ |
|
205 |
exec('cd '.$tmp_path."; find . -mtime +1 -name 'sess_*' | grep -v -w .no_delete | xargs rm > /dev/null 2> /dev/null"); |
|
206 |
} |
|
207 |
} |
|
208 |
} |
|
209 |
|
|
210 |
//###################################################################################################### |
|
211 |
// Cleanup logs in master database (only the "master-server") |
|
212 |
//###################################################################################################### |
|
213 |
|
|
214 |
if ($app->dbmaster == $app->db) { |
|
215 |
/** 7 days */ |
|
216 |
|
|
217 |
|
|
218 |
$tstamp = time() - (60*60*24*7); |
|
219 |
|
|
220 |
/* |
5de2af
|
221 |
* Keep 7 days in sys_log |
M |
222 |
* (we can delete the old items, because if they are OK, they don't interrest anymore |
|
223 |
* if they are NOT ok, the server will try to process them in 1 minute and so the |
|
224 |
* error appears again after 1 minute. So it is no problem to delete the old one! |
|
225 |
*/ |
cc7a82
|
226 |
$sql = "DELETE FROM sys_log WHERE tstamp < ? AND server_id != 0"; |
MC |
227 |
$app->dbmaster->query($sql, $tstamp); |
5de2af
|
228 |
|
b1a6a5
|
229 |
/* |
5de2af
|
230 |
* Delete all remote-actions "done" and older than 7 days |
M |
231 |
* ATTENTION: We have the same problem as described in cleaning the datalog. We must not |
|
232 |
* delete the last entry |
|
233 |
*/ |
b1a6a5
|
234 |
$sql = "SELECT max(action_id) FROM sys_remoteaction"; |
MC |
235 |
$res = $app->dbmaster->queryOneRecord($sql); |
|
236 |
$maxId = $res['max(action_id)']; |
cc7a82
|
237 |
$sql = "DELETE FROM sys_remoteaction WHERE tstamp < ? AND action_state = 'ok' AND action_id < ?"; |
MC |
238 |
$app->dbmaster->query($sql, $tstamp, $maxId); |
5de2af
|
239 |
|
b1a6a5
|
240 |
/* |
5de2af
|
241 |
* The sys_datalog is more difficult. |
M |
242 |
* 1) We have to keet ALL entries with |
|
243 |
* server_id=0, because they depend on ALL servers (even if they are not |
|
244 |
* actually in the system (and will be insered in 3 days or so). |
|
245 |
* 2) We have to keey ALL entries which are not actually precessed by the |
|
246 |
* server never mind how old they are! |
|
247 |
* 3) We have to keep the entry with the highest autoinc-id, because mysql calculates the |
|
248 |
* autoinc-id as "new value = max(row) +1" and does not store this in a separate table. |
|
249 |
* This means, if we delete to entry with the highest autoinc-value then this value is |
|
250 |
* reused as autoinc and so there are more than one entries with the same value (over |
|
251 |
* for example 4 Weeks). This is confusing for our system. |
|
252 |
* ATTENTION 2) and 3) is in some case NOT the same! so we have to check both! |
|
253 |
*/ |
|
254 |
|
b1a6a5
|
255 |
/* First we need all servers and the last sys_datalog-id they processed */ |
MC |
256 |
$sql = "SELECT server_id, updated FROM server ORDER BY server_id"; |
|
257 |
$records = $app->dbmaster->queryAllRecords($sql); |
5de2af
|
258 |
|
b1a6a5
|
259 |
/* Then we need the highest value ever */ |
MC |
260 |
$sql = "SELECT max(datalog_id) FROM sys_datalog"; |
|
261 |
$res = $app->dbmaster->queryOneRecord($sql); |
|
262 |
$maxId = $res['max(datalog_id)']; |
5de2af
|
263 |
|
b1a6a5
|
264 |
/* Then delete server by server */ |
MC |
265 |
foreach($records as $server) { |
|
266 |
$tmp_server_id = intval($server['server_id']); |
|
267 |
if($tmp_server_id > 0) { |
cc7a82
|
268 |
$sql = "DELETE FROM sys_datalog WHERE tstamp < ? AND server_id = ? AND datalog_id < ? AND datalog_id < ?"; |
MC |
269 |
// echo $sql . "\n"; |
|
270 |
$app->dbmaster->query($sql, $tstamp, $server['server_id'], $server['updated'], $maxId); |
b1a6a5
|
271 |
} |
MC |
272 |
} |
|
273 |
} |
|
274 |
|
|
275 |
|
|
276 |
parent::onRunJob(); |
|
277 |
} |
|
278 |
|
|
279 |
/* this function is optional if it contains no custom code */ |
|
280 |
public function onAfterRun() { |
|
281 |
global $app; |
|
282 |
|
|
283 |
parent::onAfterRun(); |
|
284 |
} |
5de2af
|
285 |
|
M |
286 |
} |
|
287 |
|
|
288 |
?> |