1 Star 0 Fork 0

wlnmp/cacti

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
poller_maintenance.php 18.03 KB
一键复制 编辑 原始数据 按行查看 历史
netniV 提交于 2019-01-25 08:05 . Update copyright notices for 2019
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
#!/usr/bin/php -q
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2019 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/
require(__DIR__ . '/include/cli_check.php');
require_once($config['library_path'] . '/api_data_source.php');
require_once($config['library_path'] . '/api_device.php');
require_once($config['library_path'] . '/api_graph.php');
include_once($config['library_path'] . '/poller.php');
require_once($config['library_path'] . '/rrd.php');
require_once($config['library_path'] . '/utility.php');
/* let PHP run just as long as it has to */
ini_set('max_execution_time', '0');
error_reporting(E_ALL);
$dir = dirname(__FILE__);
chdir($dir);
/* record the start time */
$poller_start = microtime(true);
global $config, $database_default, $archived, $purged, $disable_log_rotation;
/* process calling arguments */
$parms = $_SERVER['argv'];
array_shift($parms);
$debug = false;
$force = false;
$archived = 0;
$purged = 0;
if (cacti_sizeof($parms)) {
foreach ($parms as $parameter) {
if (strpos($parameter, '=')) {
list($arg, $value) = explode('=', $parameter);
} else {
$arg = $parameter;
$value = '';
}
switch ($arg) {
case '--version' :
case '-V' :
case '-v' :
display_version();
exit;
case '--help' :
case '-H' :
case '-h' :
display_help();
exit;
case '--force' :
$force = true;
break;
case '--debug' :
$debug = true;
break;
default :
print 'ERROR: Invalid Parameter ' . $parameter . "\n\n";
display_help();
exit;
}
}
}
maint_debug('Checking for Purge Actions');
if ($config['poller_id'] == 1) {
/* are my tables already present? */
$purge = db_fetch_cell('SELECT count(*)
FROM data_source_purge_action');
/* if the table that holds the actions is present, work on it */
if ($purge) {
maint_debug("Purging Required - Files Found $purge");
/* take the purge in steps */
while (true) {
maint_debug('Grabbing 1000 RRDfiles to Remove');
$file_array = db_fetch_assoc('SELECT id, name, local_data_id, action
FROM data_source_purge_action
ORDER BY name
LIMIT 1000');
if (cacti_sizeof($file_array) == 0) {
break;
}
if (cacti_sizeof($file_array) || $force) {
/* there's something to do for us now */
remove_files($file_array);
if ($force) {
cleanup_ds_and_graphs();
}
}
}
/* record the start time */
$poller_end = microtime(true);
$string = sprintf('RRDMAINT STATS: Time:%4.4f Purged:%s Archived:%s', ($poller_end - $poller_start), $purged, $archived);
cacti_log($string, true, 'SYSTEM');
}
/* removing security tokens older than 90 days */
if (read_config_option('auth_cache_enabled') == 'on') {
db_execute_prepared('DELETE FROM user_auth_cache
WHERE last_update < ?',
array(date('Y-m-d H:i:s', time()-(86400*90))));
} else {
db_execute('TRUNCATE TABLE user_auth_cache');
}
// Check expired accounts
secpass_check_expired();
}
// Check the realtime cache and poller
realtime_purge_cache();
// Remove deleted devices
api_device_purge_deleted_devices();
// Check whether the cacti log. Rotations takes place around midnight
if (isset($disable_log_rotation) && $disable_log_rotation == true) {
// Skip log rotation as it's handled by logrotate.d
} elseif (read_config_option('logrotate_enabled') == 'on') {
$frequency = read_config_option('logrotate_frequency');
if (empty($frequency)) {
$frequency = 1;
}
$last = read_config_option('logrotate_lastrun');
$now = time();
if (empty($last)) {
$last = time();
set_config_option('logrotate_lastrun', $last);
}
$date_now = new DateTime();
$date_now->setTimestamp($now);
// Take the last date/time, set the time to 59 seconds past midnight
// then remove one minute to make it the previous evening
$date_orig = new DateTime();
$date_orig->setTimestamp($last);
$date_last = new DateTime();
$date_last->setTimestamp($last)->setTime(0,0,59)->modify('-1 minute');
// Make sure we clone the last date, or we end up modifying the same object!
$date_next = clone $date_last;
$date_next->modify('+'.$frequency.'day');
cacti_log('Cacti Log Rotation - TIMECHECK Ran: ' . $date_orig->format('Y-m-d H:i:s')
. ', Now: ' . $date_now->format('Y-m-d H:i:s')
. ', Next: ' . $date_next->format('Y-m-d H:i:s'), true, 'MAINT', POLLER_VERBOSITY_HIGH);
if ($date_next < $date_now || $force) {
logrotate_rotatenow();
}
}
exit(0);
/** realtime_purge_cache() - This function will purge files in the realtime directory
* that are older than 2 hours without changes */
function realtime_purge_cache() {
/* remove all Realtime files over than 2 hours */
if (read_config_option('realtime_cache_path') != '') {
$cache_path = read_config_option('realtime_cache_path');
if (is_dir($cache_path) && is_writeable($cache_path)) {
foreach (new DirectoryIterator($cache_path) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
// only remove .png and .rrd files
if (
(substr($fileInfo->getFilename(), -4, 4) == '.png') ||
(substr($fileInfo->getFilename(), -4, 4) == '.rrd')
) {
if ((time() - $fileInfo->getMTime()) >= 7200) {
unlink($fileInfo->getRealPath());
}
}
}
}
}
db_execute("DELETE FROM poller_output_realtime WHERE time<FROM_UNIXTIME(UNIX_TIMESTAMP()-300)");
}
/*
* logrotate_rotatenow
* Rotates the cacti log
*/
function logrotate_rotatenow() {
global $config;
$poller_start = microtime(true);
$logs = array();
$log = read_config_option('path_cactilog');
if (empty($log)) {
$log = $config['base_path'] . '/log/cacti.log';
}
$logs['Cacti'] = $log;
$log = read_config_option('path_stderrlog');
if (!empty($log)) {
$logs['Cacti StdErr'] = $log;
}
$run_time = time();
set_config_option('logrotate_lastrun', $run_time);
$date = new DateTime();
$date->setTimestamp($run_time)->modify('-1day');
$rotated = 0;
$cleaned = 0;
$days = read_config_option('logrotate_retain');
if ($days == '' || $days < 0) {
$days = 7;
}
if ($days > 365) {
$days = 365;
}
foreach ($logs as $name => $log) {
$rotated += logrotate_file_rotate($name, $log, $date);
$cleaned += logrotate_file_clean($name, $log, $date, $days);
}
$cleaned += logrotate_file_clean($name, $log, $date, $days);
/* record the start time */
$poller_end = microtime(true);
$string = sprintf('LOGMAINT STATS: Time:%4.4f, Rotated:%d, Removed:%d, Days Retained:%d', ($poller_end - $poller_start), $rotated, $cleaned, $days);
cacti_log($string, true, 'SYSTEM');
}
/* logrotate_file_rotate()
* rotates the specified log file, appending date given
*/
function logrotate_file_rotate($name, $log, $date) {
if (empty($log)) {
return 0;
}
clearstatcache();
if (!file_exists($log)) {
cacti_log('Cacti Log Rotation - Skipped missing ' . $name . ' Log : ' . $log, true, 'MAINT');
return 0;
}
if (is_writable(dirname($log) . '/') && is_writable($log)) {
$perms = octdec(substr(decoct( fileperms($log) ), 2));
$owner = fileowner($log);
$group = filegroup($log);
if ($owner !== false) {
$ext = $date->format('Ymd');
if (file_exists($log . '-' . $ext)) {
$ext_inc = 1;
while (file_exists($log . '-' . $ext . '-' . $ext_inc) && $ext_inc < 99) {
$ext_inc++;
}
$ext = $ext . '-' . $ext_inc;
}
if (rename($log, $log . '-' . $ext)) {
touch($log);
chown($log, $owner);
chgrp($log, $group);
chmod($log, $perms);
cacti_log('Cacti Log Rotation - Created ' . $name . ' Log : ' . basename($log) . '-' . $ext, true, 'MAINT');
return 1;
} else {
cacti_log('Cacti Log Rotation - ERROR: Could not rename ' . $name . ' Log "' . basename($log) . '" to "' . basename($log) . '-' . $ext . '"', true, 'MAINT');
}
} else {
cacti_log('Cacti Log Rotation - ERROR: Permissions issue. Please check your ' . $name . ' Log directory : ' . basename($log), true, 'MAINT');
}
} else {
cacti_log('Cacti Log Rotation - ERROR: Permissions issue. Please check your ' . $name . ' Log as directory or file are not writable : ' . $log, true, 'MAINT');
}
return 0;
}
/*
* logrotate_file_clean
* Cleans up any old log files that should be removed
*/
function logrotate_file_clean($name, $log, $date, $rotation) {
global $config;
if (empty($log)) {
return false;
}
if ($rotation <= 0) {
return false;
}
$baselogdir = dirname($log) . '/';
$baselogname = basename($log);
clearstatcache();
$dir = scandir($baselogdir);
if (cacti_sizeof($dir)) {
$date_log = clone $date;
$date_log->modify('-'.$rotation.'day');
$e = $date_log->format('Ymd');
cacti_log('Cacti Log Rotation - Purging all ' . $name . ' logs before '. $e, true, 'MAINT');
foreach ($dir as $d) {
$fileparts = explode('-', $d);
$matches = false;
if (strpos($d, $baselogname) !== false) {
if ($fileparts > 1) {
foreach($fileparts as $p) {
// Is it in the form YYYYMMDD?
if (is_numeric($p) && strlen($p) == 8) {
$matches = true;
if ($p < $e) {
if (is_writable($baselogdir . $d)) {
@unlink($baselogdir . $d);
cacti_log('Cacti Log Rotation - Purging ' . $name . ' Log : ' . $d, true, 'MAINT');
} else {
cacti_log('Cacti Log Rotation - ERROR: Can not purge ' . $name . ' Log : ' . $d, true, 'MAINT');
}
} else {
cacti_log('Cacti Log Rotation - NOTE: Not expired, keeping ' . $name . ' Log : ' . $d, true, 'MAINT', POLLER_VERBOSITY_HIGH);
}
}
}
}
}
if ($matches) {
cacti_log('Cacti Log Rotation - NOTE: File not in expected naming format, ignoring ' . $name . ' Log : ' . $d, true, 'MAINT', POLLER_VERBOSITY_DEBUG);
}
}
}
clearstatcache();
}
/*
* secpass_check_expired
* Checks user accounts to determine if the accounts and/or their passwords should be expired
*/
function secpass_check_expired () {
maint_debug('Checking for Account / Password expiration');
// Expire Old Accounts
$e = read_config_option('secpass_expireaccount');
if ($e > 0 && is_numeric($e)) {
$t = time();
db_execute_prepared("UPDATE user_auth
SET lastlogin = ?
WHERE lastlogin = -1
AND realm = 0
AND enabled = 'on'",
array($t));
$t = $t - (intval($e) * 86400);
db_execute_prepared("UPDATE user_auth
SET enabled = ''
WHERE realm = 0
AND enabled = 'on'
AND lastlogin < ?
AND id > 1",
array($t));
}
$e = read_config_option('secpass_expirepass');
if ($e > 0 && is_numeric($e)) {
$t = time();
db_execute_prepared("UPDATE user_auth
SET lastchange = ?
WHERE lastchange = -1
AND realm = 0
AND enabled = 'on'",
array($t));
$t = $t - (intval($e) * 86400);
db_execute_prepared("UPDATE user_auth
SET must_change_password = 'on'
WHERE realm = 0
AND enabled = 'on'
AND lastchange < ?",
array($t));
}
}
/*
* remove_files
* remove all unwanted files; the list is given by table data_source_purge_action
*/
function remove_files($file_array) {
global $config, $debug, $archived, $purged;
maint_debug('RRDClean is now running on ' . cacti_sizeof($file_array) . ' items');
/* determine the location of the RRA files */
if (isset ($config['rra_path'])) {
$rra_path = $config['rra_path'];
} else {
$rra_path = $config['base_path'] . '/rra';
}
/* let's prepare the archive directory */
$rrd_archive = read_config_option('rrd_archive', true);
if ($rrd_archive == '') {
$rrd_archive = $rra_path . '/archive';
}
rrdclean_create_path($rrd_archive);
/* now scan the files */
foreach ($file_array as $file) {
$source_file = $rra_path . '/' . $file['name'];
switch ($file['action']) {
case '1' :
if (unlink($source_file)) {
maint_debug('Deleted: ' . $file['name']);
} else {
cacti_log($file['name'] . " ERROR: RRDfile Maintenance unable to delete from $rra_path!", true, 'MAINT');
}
$purged++;
break;
case '3' :
$target_file = $rrd_archive . '/' . $file['name'];
$target_dir = dirname($target_file);
if (!is_dir($target_dir)) {
rrdclean_create_path($target_dir);
}
if (rename($source_file, $target_file)) {
maint_debug('Moved: ' . $file['name'] . ' to: ' . $rrd_archive);
} else {
cacti_log($file['name'] . " ERROR: RRDfile Maintenance unable to move to $rrd_archive!", true, 'MAINT');
}
$archived++;
break;
}
/* drop from data_source_purge_action table */
db_execute_prepared('DELETE FROM `data_source_purge_action`
WHERE name = ?',
array($file['name']));
maint_debug('Delete from data_source_purge_action: ' . $file['name']);
//fetch all local_graph_id's according to this data source
$lgis = db_fetch_assoc_prepared('SELECT DISTINCT gl.id
FROM graph_local AS gl
INNER JOIN graph_templates_item AS gti
ON gl.id = gti.local_graph_id
INNER JOIN data_template_rrd AS dtr
ON dtr.id=gti.task_item_id
INNER JOIN data_local AS dl
ON dtr.local_data_id=dl.id
WHERE (local_data_id=?)',
array($file['local_data_id']));
if (cacti_sizeof($lgis)) {
/* anything found? */
maint_debug('Processing ' . cacti_sizeof($lgis) . ' Graphs for data source id: ' . $file['local_data_id']);
/* get them all */
foreach ($lgis as $item) {
$remove_lgis[] = $item['id'];
maint_debug('remove local_graph_id=' . $item['id']);
}
/* and remove them in a single run */
if (!empty ($remove_lgis)) {
api_graph_remove_multi($remove_lgis);
}
}
/* remove related data source if any */
if ($file['local_data_id'] > 0) {
maint_debug('Removing Data Source: ' . $file['local_data_id']);
api_data_source_remove($file['local_data_id']);
}
}
maint_debug('RRDClean has finished a purge pass of ' . cacti_sizeof($file_array) . ' items');
}
function rrdclean_create_path($path) {
global $config;
if (!is_dir($path)) {
if (mkdir($path, 0775)) {
if ($config['cacti_server_os'] != 'win32') {
$owner_id = fileowner($config['rra_path']);
$group_id = filegroup($config['rra_path']);
// NOTE: chown/chgrp fails for non-root users, checking their
// result is therefore irrevelevant
@chown($path, $owner_id);
@chgrp($path, $group_id);
}
} else {
cacti_log("ERROR: RRDfile Maintenance unable to create directory '" . $path . "'", false, 'MAINT');
}
}
// if path existed, we can return true
return is_dir($path) && is_writable($path);
}
/*
* cleanup_ds_and_graphs - courtesy John Rembo
*/
function cleanup_ds_and_graphs() {
global $config;
$remove_ldis = array ();
$remove_lgis = array ();
maint_debug('RRDClean now cleans up all data sources and graphs');
//fetch all local_data_id's which have appropriate data-sources
$rrds = db_fetch_assoc("SELECT local_data_id, name_cache, data_source_path
FROM data_template_data
WHERE name_cache > ''");
//filter those whose rrd files doesn't exist
foreach ($rrds as $item) {
$ldi = $item['local_data_id'];
$name = $item['name_cache'];
$ds_pth = $item['data_source_path'];
$real_pth = str_replace('<path_rra>', $config['rra_path'], $ds_pth);
if (!file_exists($real_pth)) {
if (!in_array($ldi, $remove_ldis)) {
$remove_ldis[] = $ldi;
maint_debug("RRD file is missing for data source name: $name (local_data_id=$ldi)");
}
}
}
if (empty ($remove_ldis)) {
maint_debug('No missing rrd files found');
return 0;
}
maint_debug('Processing Graphs');
//fetch all local_graph_id's according to filtered rrds
$lgis = db_fetch_assoc('SELECT DISTINCT gl.id
FROM graph_local AS gl
INNER JOIN graph_templates_item AS gti
ON gl.id=gti.local_graph_id
INNER JOIN data_template_rrd AS dtr
ON dtr.id=gti.task_item_id
INNER JOIN data_local AS dl
ON dtr.local_data_id=dl.id
WHERE (' . array_to_sql_or($remove_ldis, 'local_data_id') . ')');
foreach ($lgis as $item) {
$remove_lgis[] = $item['id'];
maint_debug('RRD file missing for local_graph_id=' . $item['id']);
}
if (!empty ($remove_lgis)) {
maint_debug('removing graphs');
api_graph_remove_multi($remove_lgis);
}
maint_debug('removing data sources');
api_data_source_remove_multi($remove_ldis);
maint_debug('removed graphs:' . cacti_count($remove_lgis) . ' removed data-sources:' . cacti_count($remove_ldis));
}
function maint_debug($message) {
global $debug;
if ($debug) {
print trim($message) . "\n";
}
}
/* display_version - displays version information */
function display_version() {
$version = get_cacti_version();
print "Cacti Maintenance Poller, Version $version, " . COPYRIGHT_YEARS . "\n";
}
/*
* display_help
* displays the usage of the function
*/
function display_help() {
display_version();
print "\nusage: poller_maintenance.php [--force] [--debug]\n\n";
print "Cacti's maintenance poller. This poller is repsonsible for executing periodic\n";
print "maintenance activities for Cacti including log rotation, deactivating accounts, etc.\n\n";
print "Optional:\n";
print " --force - Force immediate execution, e.g. for testing.\n";
print " --debug - Display verbose output during execution.\n\n";
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/whsir/cacti.git
git@gitee.com:whsir/cacti.git
whsir
cacti
cacti
master

搜索帮助