mirror of
https://github.com/Cacti/cacti.git
synced 2026-11-08 21:16:17 +09:00
This resolves the issue where the internal system hostname might not be resolvable outside the network. You can now edit the hostname url to any address (or even an IP) and it will stay set
724 lines
24 KiB
PHP
724 lines
24 KiB
PHP
#!/usr/bin/php -q
|
|
<?php
|
|
/*
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2017 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/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* tick use required as of PHP 4.3.0 to accomodate signal handling */
|
|
declare(ticks = 1);
|
|
|
|
/* we are not talking to the browser */
|
|
$no_http_headers = true;
|
|
|
|
function sig_handler($signo) {
|
|
switch ($signo) {
|
|
case SIGTERM:
|
|
case SIGINT:
|
|
cacti_log('WARNING: Cacti Master Poller process terminated by user', true, 'POLLER', POLLER_VERBOSITY_LOW);
|
|
|
|
$running_processes = db_fetch_assoc('SELECT ' . SQL_NO_CACHE . ' * FROM poller_time WHERE end_time=\'0000-00-00 00:00:00\'');
|
|
|
|
if (sizeof($running_processes)) {
|
|
foreach($running_processes as $process) {
|
|
if (function_exists('posix_kill')) {
|
|
cacti_log("WARNING: Termination poller process with pid '" . $process['pid'] . "'", true, 'POLLER', POLLER_VERBOSITY_LOW);
|
|
posix_kill($process['pid'], SIGTERM);
|
|
}
|
|
}
|
|
}
|
|
|
|
db_execute('TRUNCATE TABLE poller_time');
|
|
|
|
exit;
|
|
break;
|
|
default:
|
|
/* ignore all other signals */
|
|
}
|
|
}
|
|
|
|
/* do NOT run this script through a web browser */
|
|
if (!isset($_SERVER['argv'][0]) || isset($_SERVER['REQUEST_METHOD']) || isset($_SERVER['REMOTE_ADDR'])) {
|
|
die('<br><strong>This script is only meant to run at the command line.</strong>');
|
|
}
|
|
|
|
/* start initialization section */
|
|
include(dirname(__FILE__) . '/include/global.php');
|
|
include_once($config['base_path'] . '/lib/poller.php');
|
|
include_once($config['base_path'] . '/lib/data_query.php');
|
|
include_once($config['base_path'] . '/lib/rrd.php');
|
|
include_once($config['base_path'] . '/lib/dsstats.php');
|
|
include_once($config['base_path'] . '/lib/boost.php');
|
|
include_once($config['base_path'] . '/lib/reports.php');
|
|
|
|
/* initialize some variables */
|
|
$force = false;
|
|
$debug = false;
|
|
$mibs = false;
|
|
|
|
/* set the poller_id */
|
|
$poller_id = $config['poller_id'];
|
|
$hostname = php_uname('n');
|
|
|
|
/* requires for remote poller stage out */
|
|
chdir(dirname(__FILE__));
|
|
|
|
/* process calling arguments */
|
|
$parms = $_SERVER['argv'];
|
|
array_shift($parms);
|
|
|
|
if (sizeof($parms)) {
|
|
foreach($parms as $parameter) {
|
|
if (strpos($parameter, '=')) {
|
|
list($arg, $value) = explode('=', $parameter);
|
|
} else {
|
|
$arg = $parameter;
|
|
$value = '';
|
|
}
|
|
|
|
switch ($arg) {
|
|
case '-p':
|
|
case '--poller':
|
|
$poller_id = $value;
|
|
|
|
break;
|
|
case '-d':
|
|
case '--debug':
|
|
$debug = true;
|
|
|
|
break;
|
|
case '--force':
|
|
$force = true;
|
|
|
|
break;
|
|
case '--version':
|
|
case '-V':
|
|
case '-v':
|
|
display_version();
|
|
exit;
|
|
case '-H':
|
|
case '-h':
|
|
case '--help':
|
|
display_help();
|
|
exit;
|
|
default:
|
|
echo "ERROR: Invalid Argument: ($arg)\n\n";
|
|
display_help();
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the pollers hostname if it is blank, otherwise allow the user to edit it
|
|
if (db_fetch_cell_prepared('SELECT hostname FROM poller where id = ?', array($poller_id), 'hostname') == '') {
|
|
db_execute_prepared('UPDATE poller SET hostname = ? WHERE id = ?', array($hostname, $poller_id));
|
|
}
|
|
|
|
// Check to see if the poller is disabled
|
|
poller_enabled_check($poller_id);
|
|
|
|
// install signal handlers for UNIX only
|
|
if (function_exists('pcntl_signal')) {
|
|
pcntl_signal(SIGTERM, 'sig_handler');
|
|
pcntl_signal(SIGINT, 'sig_handler');
|
|
}
|
|
|
|
api_plugin_hook('poller_top');
|
|
|
|
// Flush the boost table if in recovery mode
|
|
poller_recovery_flush_boost($poller_id);
|
|
|
|
// Prime the poller_resource_cache for multiple pollers
|
|
update_resource_cache($poller_id);
|
|
|
|
// record the start time
|
|
$poller_start = microtime(true);
|
|
$overhead_time = 0;
|
|
|
|
// get number of polling items from the database
|
|
$poller_interval = read_config_option('poller_interval');
|
|
|
|
// retreive the last time the poller ran
|
|
$poller_lastrun = read_config_option('poller_lastrun_' . $poller_id);
|
|
|
|
// collect the system mibs every 4 hours
|
|
if ($poller_lastrun % 14440 < time() % 14440 || empty($poller_lastrun)) {
|
|
$mibs = true;
|
|
}
|
|
|
|
// get the current cron interval from the database
|
|
$cron_interval = read_config_option('cron_interval');
|
|
|
|
if ($cron_interval != 60) {
|
|
$cron_interval = 300;
|
|
}
|
|
|
|
// see if the user wishes to use process leveling
|
|
$process_leveling = read_config_option('process_leveling');
|
|
|
|
// retreive the number of concurrent process settings
|
|
$concurrent_processes = read_config_option('concurrent_processes');
|
|
|
|
// assume a scheduled task of either 60 or 300 seconds
|
|
if (isset($poller_interval)) {
|
|
$poller_runs = intval($cron_interval / $poller_interval);
|
|
$sql_where = 'WHERE rrd_next_step<=0 AND poller_id = ' . $poller_id;
|
|
|
|
define('MAX_POLLER_RUNTIME', $poller_runs * $poller_interval - 2);
|
|
}else{
|
|
$sql_where = 'WHERE poller_id = ' . $poller_id;
|
|
$poller_runs = 1;
|
|
define('MAX_POLLER_RUNTIME', 298);
|
|
}
|
|
|
|
$num_polling_items = db_fetch_cell('SELECT ' . SQL_NO_CACHE . ' COUNT(*) FROM poller_item ' . $sql_where);
|
|
if (isset($concurrent_processes) && $concurrent_processes > 1) {
|
|
$items_perhost = array_rekey(db_fetch_assoc("SELECT " . SQL_NO_CACHE . " host_id, COUNT(*) AS data_sources
|
|
FROM poller_item
|
|
$sql_where
|
|
GROUP BY host_id
|
|
ORDER BY host_id"), 'host_id', 'data_sources');
|
|
}
|
|
|
|
if (isset($items_perhost) && sizeof($items_perhost)) {
|
|
$items_per_process = floor($num_polling_items / $concurrent_processes);
|
|
|
|
if ($items_per_process == 0) {
|
|
$process_leveling = 'off';
|
|
}
|
|
}else{
|
|
$process_leveling = 'off';
|
|
}
|
|
|
|
/* some text formatting for platform specific vocabulary */
|
|
if ($config['cacti_server_os'] == 'unix') {
|
|
$task_type = 'Cron';
|
|
}else{
|
|
$task_type = 'Scheduled Task';
|
|
}
|
|
|
|
if ($debug) {
|
|
$level = POLLER_VERBOSITY_NONE;
|
|
}else{
|
|
$level = POLLER_VERBOSITY_MEDIUM;
|
|
}
|
|
|
|
$poller_seconds_sincerun = 'never';
|
|
if (isset($poller_lastrun)) {
|
|
$poller_seconds_sincerun = $poller_start - $poller_lastrun;
|
|
}
|
|
|
|
cacti_log("NOTE: Poller Int: '$poller_interval', $task_type Int: '$cron_interval', Time Since Last: '" . round($poller_seconds_sincerun,2) . "', Max Runtime '" . MAX_POLLER_RUNTIME. "', Poller Runs: '$poller_runs'", true, 'POLLER', $level);
|
|
|
|
/* our cron can run at either 1 or 5 minute intervals */
|
|
if ($poller_interval <= 60) {
|
|
$min_period = '60';
|
|
}else{
|
|
$min_period = '300';
|
|
}
|
|
|
|
/* get to see if we are polling faster than reported by the settings, if so, exit */
|
|
if ((isset($poller_lastrun) && isset($poller_interval) && $poller_lastrun > 0) && (!$force)) {
|
|
/* give the user some flexibility to run a little moe often */
|
|
if ((($poller_start - $poller_lastrun)*1.3) < MAX_POLLER_RUNTIME) {
|
|
cacti_log("NOTE: $task_type is configured to run too often! The Poller Interval is '$poller_interval' seconds, with a minimum $task_type period of '$min_period' seconds, but only " . number_format_i18n($poller_start - $poller_lastrun, 1) . ' seconds have passed since the poller last ran.', true, 'POLLER', $level);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/* check to see whether we have the poller interval set lower than the poller is actually ran, if so, issue a warning */
|
|
if ((($poller_start - $poller_lastrun - 5) > MAX_POLLER_RUNTIME) && ($poller_lastrun > 0)) {
|
|
cacti_log("WARNING: $task_type is out of sync with the Poller Interval! The Poller Interval is '$poller_interval' seconds, with a maximum of a '$min_period' second $task_type, but " . number_format_i18n($poller_start - $poller_lastrun, 1) . ' seconds have passed since the last poll!', true, 'POLLER');
|
|
}
|
|
|
|
db_execute_prepared('REPLACE INTO settings
|
|
(name, value)
|
|
VALUES (?, ?)',
|
|
array('poller_lastrun_' . $poller_id, (int)$poller_start));
|
|
|
|
/* let PHP only run 1 second longer than the max runtime, plus the poller needs lot's of memory */
|
|
ini_set('max_execution_time', MAX_POLLER_RUNTIME + 1);
|
|
ini_set('memory_limit', '512M');
|
|
|
|
$poller_runs_completed = 0;
|
|
$poller_items_total = 0;
|
|
|
|
while ($poller_runs_completed < $poller_runs) {
|
|
/* record the start time for this loop */
|
|
$loop_start = microtime(true);
|
|
|
|
if ($poller_id == '1') {
|
|
$polling_hosts = array_merge(
|
|
array(0 => array('id' => '0')),
|
|
db_fetch_assoc_prepared('SELECT ' . SQL_NO_CACHE . ' id
|
|
FROM host
|
|
WHERE poller_id = ?
|
|
AND disabled=""
|
|
ORDER BY id', array($poller_id)));
|
|
}else{
|
|
$polling_hosts = db_fetch_assoc_prepared('SELECT ' . SQL_NO_CACHE . ' id
|
|
FROM host
|
|
WHERE poller_id = ?
|
|
AND disabled=""
|
|
ORDER BY id', array($poller_id));
|
|
}
|
|
|
|
$script = $server = $snmp = 0;
|
|
$totals = db_fetch_assoc_prepared('SELECT action, count(*) AS totals FROM poller_item WHERE poller_id = ? GROUP BY action', array($poller_id));
|
|
if (sizeof($totals)) {
|
|
foreach($totals as $value) {
|
|
switch($value['action']) {
|
|
case '0': // SNMP
|
|
$snmp = $value['totals'];
|
|
break;
|
|
case '1': // Script
|
|
$script = $value['totals'];
|
|
break;
|
|
case '2': // Server
|
|
$server = $value['totals'];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* update statistics */
|
|
db_execute_prepared('INSERT INTO poller (id, snmp, script, server, last_status, status)
|
|
VALUES (?, ?, ?, ?, NOW(), 1)
|
|
ON DUPLICATE KEY UPDATE snmp=VALUES(snmp), script=VALUES(script),
|
|
server=VALUES(server), last_status=VALUES(last_status), status=VALUES(status)',
|
|
array($poller_id, $snmp, $script, $server));
|
|
|
|
/* calculate overhead time */
|
|
if ($overhead_time == 0) {
|
|
$overhead_time = $loop_start - $poller_start;
|
|
}
|
|
|
|
/* initialize counters for script file handling */
|
|
$host_count = 1;
|
|
|
|
/* initialize file creation flags */
|
|
$change_proc = false;
|
|
|
|
/* initialize file and host count pointers */
|
|
$started_processes = 0;
|
|
$first_host = 0;
|
|
$last_host = 0;
|
|
|
|
/* update web paths for the poller */
|
|
db_execute("REPLACE INTO settings (name, value) VALUES ('path_webroot','" . addslashes(($config['cacti_server_os'] == 'win32') ? strtr(strtolower(substr(dirname(__FILE__), 0, 1)) . substr(dirname(__FILE__), 1),"\\", '/') : dirname(__FILE__)) . "')");
|
|
|
|
/* obtain some defaults from the database */
|
|
$poller_type = read_config_option('poller_type');
|
|
$max_threads = read_config_option('max_threads');
|
|
|
|
/* initialize poller_time and poller_output tables, check poller_output for issues */
|
|
$running_processes = db_fetch_cell_prepared('SELECT ' . SQL_NO_CACHE . ' COUNT(*)
|
|
FROM poller_time
|
|
WHERE poller_id = ?
|
|
AND end_time="0000-00-00 00:00:00"', array($poller_id));
|
|
|
|
if ($running_processes) {
|
|
cacti_log("WARNING: There are '$running_processes' detected as overrunning a polling process, please investigate", true, 'POLLER');
|
|
}
|
|
|
|
db_execute_prepared('DELETE FROM poller_time WHERE poller_id = ?', array($poller_id));
|
|
|
|
// Only report issues for the main poller or from bad local data ids, other pollers may insert somewhat asynchornously
|
|
$issues_limit = 20;
|
|
|
|
if ($poller_id == 1) {
|
|
$issues = db_fetch_assoc_prepared('SELECT ' . SQL_NO_CACHE . ' local_data_id, rrd_name
|
|
FROM poller_output AS po
|
|
LEFT JOIN data_local AS dl
|
|
ON po.local_data_id=dl.id
|
|
LEFT JOIN host AS h
|
|
ON dl.host_id=h.id
|
|
WHERE h.poller_id = ? OR h.id IS NULL LIMIT ' . $issues_limit, array($poller_id));
|
|
}else{
|
|
if ($config['connection'] == 'online') {
|
|
$issues = db_fetch_assoc_prepared('SELECT ' . SQL_NO_CACHE . ' local_data_id, rrd_name
|
|
FROM poller_output AS po
|
|
LEFT JOIN data_local AS dl
|
|
ON po.local_data_id=dl.id
|
|
LEFT JOIN host AS h
|
|
ON dl.host_id=h.id
|
|
WHERE (h.poller_id = ? OR h.id IS NULL)
|
|
AND time < FROM_UNIXTIME(UNIX_TIMESTAMP()-600)
|
|
LIMIT ' . $issues_limit, array($poller_id));
|
|
}else{
|
|
$issues = array();
|
|
}
|
|
}
|
|
|
|
if (sizeof($issues)) {
|
|
$count = db_fetch_cell_prepared('SELECT ' . SQL_NO_CACHE . ' COUNT(*)
|
|
FROM poller_output AS po
|
|
LEFT JOIN data_local AS dl
|
|
ON po.local_data_id=dl.id
|
|
LEFT JOIN host AS h
|
|
ON dl.host_id=h.id
|
|
WHERE h.poller_id = ? OR h.id IS NULL', array($poller_id));
|
|
|
|
$issue_list = '';
|
|
foreach($issues as $issue) {
|
|
$issue_list .= (strlen($issue_list) ? ', ' : '') . $issue['rrd_name'] . '(DS[' . $issue['local_data_id'] . '])';
|
|
}
|
|
|
|
if ($count > $issues_limit) {
|
|
$issue_list .= ", Additional Issues Remain. Only showing first $issues_limit";
|
|
}
|
|
|
|
cacti_log("WARNING: Poller Output Table not Empty. Issues Found: $count, Data Sources: $issue_list", true, 'POLLER');
|
|
|
|
db_execute_prepared('DELETE po
|
|
FROM poller_output AS po
|
|
LEFT JOIN data_local AS dl
|
|
ON po.local_data_id=dl.id
|
|
LEFT JOIN host AS h
|
|
ON dl.host_id=h.id
|
|
WHERE h.poller_id = ? OR h.id IS NULL', array($poller_id));
|
|
}
|
|
|
|
/* mainline */
|
|
if (read_config_option('poller_enabled') == 'on') {
|
|
/* determine the number of hosts to process per file */
|
|
$hosts_per_process = ceil(sizeof($polling_hosts) / $concurrent_processes );
|
|
|
|
$items_launched = 0;
|
|
|
|
/* exit poller if spine is selected and file does not exist */
|
|
if (($poller_type == '2') && (!file_exists(read_config_option('path_spine')))) {
|
|
cacti_log('ERROR: The path: ' . read_config_option('path_spine') . ' is invalid. Can not continue', true, 'POLLER');
|
|
exit;
|
|
}
|
|
|
|
/* Determine Command Name */
|
|
if ($poller_type == '2') {
|
|
$command_string = read_config_option('path_spine');
|
|
if (read_config_option('path_spine_config') != '' && file_exists(read_config_option('path_spine_config'))) {
|
|
$extra_args = ' -C ' . read_config_option('path_spine_config');
|
|
}else{
|
|
$extra_args = '';
|
|
}
|
|
|
|
$method = 'spine';
|
|
$total_procs = $concurrent_processes * $max_threads;
|
|
chdir(dirname(read_config_option('path_spine')));
|
|
}else if ($config['cacti_server_os'] == 'unix') {
|
|
$command_string = read_config_option('path_php_binary');
|
|
$extra_args = '-q "' . $config['base_path'] . '/cmd.php"';
|
|
$method = 'cmd.php';
|
|
$total_procs = $concurrent_processes;
|
|
}else{
|
|
$command_string = read_config_option('path_php_binary');
|
|
$extra_args = '-q "' . strtolower($config['base_path'] . '/cmd.php"');
|
|
$method = 'cmd.php';
|
|
$total_procs = $concurrent_processes;
|
|
}
|
|
|
|
$extra_args = api_plugin_hook_function('poller_command_args', $extra_args);
|
|
|
|
if ($poller_id > 1) {
|
|
$extra_args .= ' --mode=' . $config['connection'];
|
|
}
|
|
|
|
/* Populate each execution file with appropriate information */
|
|
foreach ($polling_hosts as $item) {
|
|
if ($host_count == 1) {
|
|
$first_host = $item['id'];
|
|
}
|
|
|
|
if ($process_leveling != 'on') {
|
|
if ($host_count == $hosts_per_process) {
|
|
$last_host = $item['id'];
|
|
$change_proc = true;
|
|
}
|
|
}else{
|
|
if (isset($items_perhost[$item['id']])) {
|
|
$items_launched += $items_perhost[$item['id']];
|
|
}
|
|
|
|
if (($items_launched >= $items_per_process) ||
|
|
(sizeof($items_perhost) == $concurrent_processes)) {
|
|
$last_host = $item['id'];
|
|
/* if this is the dummy entry for externally updated data sources
|
|
* that are not related to any host (host id = 0), do NOT change_proc */
|
|
$change_proc = ($item['id'] == 0 ? false : true);
|
|
$items_launched = 0;
|
|
}
|
|
}
|
|
|
|
$host_count ++;
|
|
|
|
if ($change_proc) {
|
|
exec_background($command_string, "$extra_args --poller=$poller_id --first=$first_host --last=$last_host" . ($mibs ? ' --mibs':''));
|
|
usleep(100000);
|
|
|
|
$host_count = 1;
|
|
$change_proc = false;
|
|
$first_host = 0;
|
|
$last_host = 0;
|
|
|
|
$started_processes++;
|
|
} /* end change_process */
|
|
} /* end for each */
|
|
|
|
/* launch the last process */
|
|
if ($host_count > 1) {
|
|
$last_host = $item['id'];
|
|
|
|
exec_background($command_string, "$extra_args --poller=$poller_id --first=$first_host --last=$last_host");
|
|
usleep(100000);
|
|
|
|
$started_processes++;
|
|
}
|
|
|
|
if ($poller_id == 1) {
|
|
/* insert the current date/time for graphs */
|
|
db_execute("REPLACE INTO settings (name, value) VALUES ('date', NOW())");
|
|
|
|
/* open a pipe to rrdtool for writing */
|
|
$rrdtool_pipe = rrd_init();
|
|
}
|
|
|
|
if ($poller_type == '1') {
|
|
$max_threads = 'N/A';
|
|
}
|
|
|
|
$rrds_processed = 0;
|
|
$poller_finishing_dispatched = false;
|
|
while (1) {
|
|
$finished_processes = db_fetch_cell_prepared('SELECT ' . SQL_NO_CACHE . " count(*)
|
|
FROM poller_time
|
|
WHERE poller_id = ?
|
|
AND end_time >'0000-00-00 00:00:00'", array($poller_id));
|
|
|
|
if ($finished_processes >= $started_processes) {
|
|
/* all scheduled pollers are finished */
|
|
if ($poller_finishing_dispatched === false) {
|
|
api_plugin_hook('poller_finishing');
|
|
$poller_finishing_dispatched = true;
|
|
}
|
|
|
|
if ($poller_id == 1) {
|
|
$rrds_processed = $rrds_processed + process_poller_output($rrdtool_pipe, true);
|
|
}
|
|
|
|
log_cacti_stats($loop_start, $method, $concurrent_processes, $max_threads,
|
|
sizeof($polling_hosts), $hosts_per_process, $num_polling_items, $rrds_processed);
|
|
|
|
break;
|
|
}else {
|
|
if (read_config_option('log_verbosity') >= POLLER_VERBOSITY_MEDIUM || $debug) {
|
|
print 'Waiting on ' . ($started_processes - $finished_processes) . ' of ' . $started_processes . " pollers.\n";
|
|
}
|
|
|
|
$mtb = microtime(true);
|
|
|
|
if ($poller_id == 1) {
|
|
$rrds_processed = $rrds_processed + process_poller_output($rrdtool_pipe);
|
|
}
|
|
|
|
/* end the process if the runtime exceeds MAX_POLLER_RUNTIME */
|
|
if (($poller_start + MAX_POLLER_RUNTIME) < time()) {
|
|
cacti_log('Maximum runtime of ' . MAX_POLLER_RUNTIME . ' seconds exceeded. Exiting.', true, 'POLLER');
|
|
|
|
/* generate a snmp notification */
|
|
snmpagent_poller_exiting();
|
|
|
|
api_plugin_hook_function('poller_exiting');
|
|
log_cacti_stats($loop_start, $method, $concurrent_processes, $max_threads,
|
|
sizeof($polling_hosts), $hosts_per_process, $num_polling_items, $rrds_processed);
|
|
|
|
break;
|
|
}else if (microtime(true) - $mtb < 1) {
|
|
sleep(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($poller_id == 1) {
|
|
rrd_close($rrdtool_pipe);
|
|
}
|
|
|
|
/* process poller commands */
|
|
if (db_fetch_cell_prepared('SELECT ' . SQL_NO_CACHE . ' COUNT(*) FROM poller_command WHERE poller_id = ?', array($poller_id)) > 0) {
|
|
$command_string = read_config_option('path_php_binary');
|
|
$extra_args = '-q "' . $config['base_path'] . "/poller_commands.php\" --poller=$poller_id";
|
|
exec_background($command_string, $extra_args);
|
|
} else {
|
|
/* no re-index or Rechache present on this run
|
|
* in case, we have more PCOMMANDS than recaching, this has to be moved to poller_commands.php
|
|
* but then we'll have to call it each time to make sure, stats are updated */
|
|
db_execute("REPLACE INTO settings (name,value) VALUES ('stats_recache_$poller_id','RecacheTime:0.0 DevicesRecached:0')");
|
|
}
|
|
|
|
if ($method == 'spine') {
|
|
$webroot = read_config_option('path_webroot');
|
|
|
|
if (is_dir($webroot)) {
|
|
chdir($webroot);
|
|
}
|
|
}
|
|
}else{
|
|
cacti_log('NOTE: There are no items in your poller for this polling cycle!', true, 'POLLER', $level);
|
|
}
|
|
|
|
$poller_runs_completed++;
|
|
|
|
/* record the start time for this loop */
|
|
$loop_end = microtime(true);
|
|
$loop_time = $loop_end - $loop_start;
|
|
|
|
if ($loop_time < $poller_interval) {
|
|
/* sleep the appripriate amount of time */
|
|
if ($poller_runs_completed < $poller_runs) {
|
|
$plugin_start = microtime(true);
|
|
|
|
/* all plugins moved to core */
|
|
if ($poller_id == 1) {
|
|
snmpagent_poller_bottom();
|
|
dsstats_poller_bottom();
|
|
boost_poller_bottom();
|
|
api_plugin_hook('poller_bottom');
|
|
}
|
|
|
|
/* record the start time for this loop */
|
|
$loop_end = microtime(true);
|
|
$cur_loop_time = $loop_end - $loop_start;
|
|
|
|
if ($poller_runs_completed == 1) {
|
|
$sleep_time = $poller_interval - $cur_loop_time - $overhead_time;
|
|
} else {
|
|
$sleep_time = $poller_interval - $cur_loop_time;
|
|
}
|
|
|
|
/* log some nice debug information */
|
|
if ($debug) {
|
|
echo 'Loop Time is: ' . round($loop_time, 2) . "\n";
|
|
echo 'Sleep Time is: ' . round($sleep_time, 2) . "\n";
|
|
echo 'Total Time is: ' . round($loop_end - $poller_start, 2) . "\n";
|
|
}
|
|
|
|
$plugin_end = microtime(true);
|
|
if (($sleep_time - ($plugin_end - $plugin_start)) > 0) {
|
|
usleep(($sleep_time - ($plugin_end - $plugin_start)) * 1000000);
|
|
}
|
|
|
|
api_plugin_hook('poller_top');
|
|
}
|
|
}else{
|
|
cacti_log('WARNING: Cacti Polling Cycle Exceeded Poller Interval by ' . $loop_end-$loop_start-$poller_interval . ' seconds', true, 'POLLER', $level);
|
|
}
|
|
}
|
|
|
|
function poller_enabled_check($poller_id) {
|
|
$disabled = db_fetch_cell_prepared('SELECT disabled FROM poller WHERE id = ?', array($poller_id));
|
|
|
|
if ($disabled == 'on') {
|
|
db_execute_prepared('UPDATE poller SET last_status=NOW() WHERE id = ?', array($poller_id));
|
|
cacti_log('WARNING: Poller ' . $poller_id . ' is Disabled, graphing or other activities are running', true, 'SYSTEM');
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
function log_cacti_stats($loop_start, $method, $concurrent_processes, $max_threads, $num_hosts,
|
|
$hosts_per_process, $num_polling_items, $rrds_processed) {
|
|
global $poller_id;
|
|
|
|
/* take time and log performance data */
|
|
$loop_end = microtime(true);
|
|
|
|
$perf_data = array(
|
|
round($loop_end-$loop_start,4),
|
|
$method,
|
|
$concurrent_processes,
|
|
$max_threads,
|
|
$num_hosts,
|
|
$hosts_per_process,
|
|
$num_polling_items,
|
|
$rrds_processed
|
|
);
|
|
|
|
$cacti_stats = vsprintf('Time:%01.4f Method:%s Processes:%s Threads:%s Hosts:%s HostsPerProcess:%s DataSources:%s RRDsProcessed:%s', $perf_data);
|
|
cacti_log('STATS: ' . $cacti_stats , true, 'SYSTEM');
|
|
|
|
/* insert poller stats into the settings table */
|
|
db_execute_prepared('REPLACE INTO settings (name, value) VALUES ("stats_poller",?)', array($cacti_stats));
|
|
db_execute_prepared('INSERT INTO poller (id, total_time, last_update, last_status, status)
|
|
VALUES (?, ?, NOW(), NOW(), 2)
|
|
ON DUPLICATE KEY UPDATE total_time=VALUES(total_time), last_update=VALUES(last_update),
|
|
last_status=VALUES(last_status), status=VALUES(status)',
|
|
array($poller_id, round($loop_end-$loop_start,4)));
|
|
|
|
/* update snmpcache */
|
|
snmpagent_cacti_stats_update($perf_data);
|
|
|
|
api_plugin_hook_function('cacti_stats_update', $perf_data);
|
|
}
|
|
|
|
/**
|
|
* function for bulk spikekill that only runs on the main cacti server
|
|
*/
|
|
function spikekill_poller_bottom () {
|
|
global $config;
|
|
include_once($config['base_path'] . '/lib/poller.php');
|
|
|
|
$command_string = read_config_option('path_php_binary');
|
|
$extra_args = '-q ' . $config['base_path'] . '/poller_spikekill.php';
|
|
exec_background($command_string, $extra_args);
|
|
}
|
|
|
|
/* display_version - displays version information */
|
|
function display_version() {
|
|
$version = db_fetch_cell('SELECT cacti FROM version');
|
|
echo "Cacti Main Poller, Version $version, " . COPYRIGHT_YEARS . "\n";
|
|
}
|
|
|
|
function display_help() {
|
|
display_version();
|
|
|
|
echo "\nusage: poller.php [--poller=ID] [--force] [--debug]\n\n";
|
|
echo "Cacti's main poller. This poller is the launcher of cmd.php, spine, and all other\n";
|
|
echo "background processes. It is the heart of Cacti's data collection engine.\n\n";
|
|
echo "Optional:\n";
|
|
echo " --poller=ID Run as the poller indicated and not the default poller.\n";
|
|
echo " --force Override poller overrun detection and force a poller run.\n";
|
|
echo " --debug|-d Output debug information. Similar to cacti's DEBUG logging level.\n\n";
|
|
}
|
|
|
|
/* start post data processing */
|
|
if ($poller_id == 1) {
|
|
snmpagent_poller_bottom();
|
|
boost_poller_bottom();
|
|
dsstats_poller_bottom();
|
|
reports_poller_bottom();
|
|
spikekill_poller_bottom();
|
|
automation_poller_bottom();
|
|
poller_maintenance();
|
|
api_plugin_hook('poller_bottom');
|
|
}else{
|
|
automation_poller_bottom();
|
|
poller_maintenance();
|
|
}
|
|
|
|
|