diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6172227..0167f80 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,8 +7,11 @@
* feature: Add cpu/memory statistics
* feature: Better process control
* feature: Add return data size stats
-* feature: Add log renention
+* feature: Add log retention
* feature: Command run only for selected tests
+* feature: Add configurable test timeout
+* feature: Add Servcheck graph template
+* issue: Better themes support
--- 0.3 ---
diff --git a/README.md b/README.md
index 3997aa7..1a66b34 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,11 @@
This is Cacti's Services monitoring plugin. Based on Webseer plugin.
This plugin allows you to add service monitoring to Cacti.
-You simply add service check, allow service specific test
+You simply add service check, allow service specific test
(like certificate check, long duration check, ...)
-and you can add the expected response. Servcheck periodically run test
+and you can add the expected response. Servcheck periodically run test
and notify if a service check fails. The plugin records statistics
-about the connection and service response. Servcheck can send email notification
+about the connection and service response. Servcheck can send email notification
or run script when the status changes.
This plugin, like many others, integrates with Cacti's Maintenance or 'maint'
@@ -18,10 +18,10 @@ take place during maintenance periods.
## Tests and results
-Setvcheck try to run test once or more than once (you can configure it).
-If successful on the first attempt, no further
-tests will be performed. Main result is ok/error. A lot of information
-are returned with main result. After the test is completed, statistics are generated.
+Setvcheck try to run test once or more than once (you can configure it).
+If successful on the first attempt, no further tests will be performed.
+Main result is ok/error. A lot of information are returned with main result.
+After the test is completed, statistics are generated.
Based on the statistics, email notifications can be sent:
- service state change
- search text in result change
@@ -45,6 +45,8 @@ MQTT - try to subscribe topic or wait for any message and print result
SNMP - get or walk specified OID and return answer
SSH_COMMAND - ssh connect, run command and return output
+## Graph template
+You can create graph for each test. How to and template is in templates directory.
## Important
Servcheck has great debug output. If you have any problem, try to run your test:
@@ -52,11 +54,15 @@ Servcheck has great debug output. If you have any problem, try to run your test:
Example_script.sh shows you how to use returned variables in own script.
+Test duration - default test duration is 5 seconds, you can change it in settings. If you need different for
+specific test, change "Long duration alert" parametr in test. After that the max. duration will be
+Long duration alert + 2 seconds.
+
Recommendation for tests with download - please download only small not binary files.
Default Libcurl build doesn't compile all services. You have to compile again for SMB, LDAP, ...
-For POP3 and IMAP tests is better insert correct username and password. Without credentials,
+For POP3 and IMAP tests is better insert correct username and password. Without credentials,
curl can will return incorrect result.
SCP is in insecure mode - doesn't check SSH server key!
diff --git a/includes/arrays.php b/includes/arrays.php
index 04639a3..c177a4b 100644
--- a/includes/arrays.php
+++ b/includes/arrays.php
@@ -42,30 +42,12 @@
];
$servcheck_states = [
- 'error' => [
- 'color' => '#FB4A14',
- 'display' => __('Error', 'servcheck')
- ],
- 'duration' => [
- 'color' => '#CDFDFF',
- 'display' => __('Long duration', 'servcheck')
- ],
- 'warning' => [
- 'color' => '#FCAA94',
- 'display' => __('Warning', 'servcheck')
- ],
- 'failing' => [
- 'color' => '#FAFD9E',
- 'display' => __('Failing', 'servcheck')
- ],
- 'ok' => [
- 'color' => '#E0FFE0',
- 'display' => __('Ok', 'servcheck')
- ],
- 'disabled' => [
- 'color' => '#CDCFC4',
- 'display' => __('Disabled', 'servcheck')
- ]
+ 'error' => __('Error', 'servcheck'),
+ 'duration' => __('Long duration', 'servcheck'),
+ 'warning' => __('Warning', 'servcheck'),
+ 'failing' => __('Failing', 'servcheck'),
+ 'ok' => __('Ok', 'servcheck'),
+ 'disabled' => __('Disabled', 'servcheck')
];
$service_types = [
@@ -555,7 +537,7 @@
'default' => 0,
'max_length' => '5',
'size' => '30',
- 'description' => __('If the test time is greater than this value more times in a row, send a notification. Related to variable Duration count.', 'servcheck'),
+ 'description' => __('If the test time is greater than this value more times in a row, send a notification. Related to variable Duration count. The test inherits the maximum runtime from the settings. If a higher value is set here, the maximum runtime is this value + 2 seconds.', 'servcheck'),
'value' => '|arg1:duration_trigger|',
],
'duration_count' => [
@@ -936,7 +918,7 @@
'ftp_scp' => __('Encrypted SCP connection, login and try to download file specified in path (/path/to/file.txt).', 'servcheck'),
'smb_smb' => __('Try SMB protocol, username and password are required. Try to login and download file.', 'servcheck'),
'smb_smbs' => __('Try SMB protocol, username and password are required. Try to login and download file.', 'servcheck'),
- 'mqtt_mqtt' => __('Connetct to MQTT server and listen for any message. You can specify topic in Path (bedroom/temp), blank for any topic', 'servcheck'),
+ 'mqtt_mqtt' => __('Connetct to MQTT server and listen for any message. You can specify topic in Path (bedroom/temp), blank for any topic. For this test is recommended increase \"Long duration alert\"', 'servcheck'),
'rest_basic' => __('REST API test with basic HTTP auth. Prepare credential first.', 'servcheck'),
'rest_apikey' => __('REST API test with API key auth. Prepare credential first.', 'servcheck'),
'rest_oauth2' => __('REST API test with Oauth2. Prepare credential first.', 'servcheck'),
diff --git a/includes/functions.php b/includes/functions.php
index da945ae..dab56e2 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -63,6 +63,13 @@ function servcheck_check_debug() {
}
}
+/**
+ * Log debug message
+ *
+ * @param string $message Text of the message that will be logged
+ *
+ * @return void
+ */
function servcheck_debug($message = '') {
global $debug;
@@ -226,7 +233,7 @@ function servcheck_legend() {
print '
';
foreach ($servcheck_states as $index => $state) {
- print '' . $state['display'] . ' ';
+ print '' . $state . ' ';
}
print ' ';
diff --git a/includes/test_curl.php b/includes/test_curl.php
index 26dfcd8..e16a1aa 100644
--- a/includes/test_curl.php
+++ b/includes/test_curl.php
@@ -44,7 +44,7 @@ function curl_try($test) {
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 4,
- CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 1) : 5,
+ CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
CURLOPT_CAINFO => $ca_info,
];
diff --git a/includes/test_dns.php b/includes/test_dns.php
index a59d873..cdb17bd 100644
--- a/includes/test_dns.php
+++ b/includes/test_dns.php
@@ -38,7 +38,7 @@ function dns_try($test) {
servcheck_debug('Querying ' . $test['hostname'] . ' for record ' . $test['dns_query']);
- $a = new mxlookup($test['dns_query'], $test['hostname'], $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 3) : 5);
+ $a = new mxlookup($test['dns_query'], $test['hostname'], $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'));
if (!cacti_sizeof($a->arrMX)) {
$results['result'] = 'error';
@@ -117,7 +117,7 @@ function doh_try($test) {
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 4,
- CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 3) : 5,
+ CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
CURLOPT_CAINFO => $ca_info,
];
diff --git a/includes/test_ftp.php b/includes/test_ftp.php
index fb7e285..1affa0a 100644
--- a/includes/test_ftp.php
+++ b/includes/test_ftp.php
@@ -43,7 +43,7 @@ function ftp_try($test) {
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 4,
- CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 1) : 5,
+ CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
CURLOPT_CAINFO => $ca_info,
];
diff --git a/includes/test_mail.php b/includes/test_mail.php
index 0c963d9..a7043dd 100644
--- a/includes/test_mail.php
+++ b/includes/test_mail.php
@@ -123,7 +123,7 @@ function mail_try($test) {
'tcp://' . $test['hostname'],
$errno,
$errstr,
- 3,
+ $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
STREAM_CLIENT_CONNECT,
$context
);
@@ -153,7 +153,7 @@ function mail_try($test) {
'ssl://' . $test['hostname'],
$errno,
$errstr,
- 3,
+ $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
STREAM_CLIENT_CONNECT,
$context
);
@@ -204,7 +204,7 @@ function mail_try($test) {
'tcp://' . $test['hostname'],
$errno,
$errstr,
- 3,
+ $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
STREAM_CLIENT_CONNECT,
$context
);
@@ -283,7 +283,7 @@ function mail_try($test) {
$method . '://' . $test['hostname'],
$errno,
$errstr,
- 3,
+ $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
STREAM_CLIENT_CONNECT,
$context
);
@@ -364,7 +364,7 @@ function mail_try($test) {
$method . '://' . $test['hostname'],
$errno,
$errstr,
- 3,
+ $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
STREAM_CLIENT_CONNECT,
$context
);
diff --git a/includes/test_mqtt.php b/includes/test_mqtt.php
index a533945..1d6c2bb 100644
--- a/includes/test_mqtt.php
+++ b/includes/test_mqtt.php
@@ -126,7 +126,7 @@ function mqtt_try($test) {
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FILE => $file,
- CURLOPT_TIMEOUT => 7,
+ CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'),
CURLOPT_NOPROGRESS => false,
CURLOPT_XFERINFOFUNCTION => function ($download_size, $downloaded, $upload_size, $uploaded) {
if ($downloaded > 0) {
diff --git a/includes/test_restapi.php b/includes/test_restapi.php
index 82b3d24..f8ec93b 100644
--- a/includes/test_restapi.php
+++ b/includes/test_restapi.php
@@ -42,7 +42,7 @@ function restapi_try($test) {
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 4,
- CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 3) : 5,
+ CURLOPT_TIMEOUT => $test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 3) : read_config_option('servcheck_test_max_duration'),
CURLOPT_CAINFO => $ca_info,
];
diff --git a/includes/test_snmp.php b/includes/test_snmp.php
index deb6121..ec894fb 100644
--- a/includes/test_snmp.php
+++ b/includes/test_snmp.php
@@ -29,6 +29,7 @@ function snmp_try($test) {
$version = 2;
$port = 161;
+ $timeout = ($test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration')) * 1000;
// default result
$results['result'] = 'error';
@@ -97,12 +98,14 @@ function snmp_try($test) {
servcheck_debug('SNMP GET request, hostname ' . $test['hostname'] . ':' . $port);
$data = cacti_snmp_get($test['hostname'], $credential['community'], $test['snmp_oid'], $version,
$credential['snmp_username'], $credential['snmp_password'], $credential['snmp_auth_protocol'],
- $credential['snmp_priv_passphrase'], $credential['snmp_priv_protocol'], $credential['snmp_context'], $port);
+ $credential['snmp_priv_passphrase'], $credential['snmp_priv_protocol'], $credential['snmp_context'],
+ $port, $timeout);
} else {
servcheck_debug('SNMP WALK request, hostname ' . $test['hostname'] . ':' . $port);
$data = cacti_snmp_walk($test['hostname'], $credential['community'], $test['snmp_oid'], $version,
$credential['snmp_username'], $credential['snmp_password'], $credential['snmp_auth_protocol'],
- $credential['snmp_priv_passphrase'], $credential['snmp_priv_protocol'], $credential['snmp_context'], $port);
+ $credential['snmp_priv_passphrase'], $credential['snmp_priv_protocol'], $credential['snmp_context'],
+ $port, $timeout);
$data = var_export($data, true);
}
diff --git a/includes/test_ssh.php b/includes/test_ssh.php
index 01bdee5..80f0777 100644
--- a/includes/test_ssh.php
+++ b/includes/test_ssh.php
@@ -61,6 +61,8 @@ function ssh_try($test) {
$ssh->enableQuietMode();
}
+ $ssh->setTimeout($test['duration_trigger'] > 0 ? ($test['duration_trigger'] + 2) : read_config_option('servcheck_test_max_duration'));
+
if ($test['cred_id'] > 0) {
$cred = db_fetch_row_prepared('SELECT * FROM plugin_servcheck_credential WHERE id = ?',
[$test['cred_id']]);
diff --git a/poller_servcheck.php b/poller_servcheck.php
index fee765c..7d2b3b5 100644
--- a/poller_servcheck.php
+++ b/poller_servcheck.php
@@ -60,7 +60,6 @@
$debug = false;
$force = false;
$start = microtime(true);
-$test_id = 0;
$test_cond = '';
$poller_id = $config['poller_id'];
$poller_int = read_config_option('poller_interval');
@@ -75,15 +74,6 @@
}
switch ($arg) {
- case '--id':
- if (is_numeric($value) && $value > 0) {
- $test_id = $value;
- } else {
- print "FATAL: Option 'id' is not numeric" . PHP_EOL;
- exit(1);
- }
-
- break;
case '-f':
case '--force':
$force = true;
@@ -162,63 +152,51 @@
}
}
+$max_processes = read_config_option('servcheck_processes');
+
+if (empty($max_processes)) {
+ $max_processes = 8;
+}
+
$params = [];
$params[] = $poller_id;
-$sql_where = ' AND poller_id = ?';
+$sql_where = 'poller_id = ? ';
-if ($test_id > 0) {
- $sql_where = ' AND id = ?';
- $params[] = $test_id;
+if (!$force) {
+ $sql_where .= 'AND enabled = "on" ';
}
-$tests = db_fetch_assoc_prepared("SELECT *
+$tests = db_fetch_cell_prepared("SELECT COUNT(id)
FROM plugin_servcheck_test
- WHERE enabled = 'on'
+ WHERE
$sql_where",
$params);
-$max_processes = read_config_option('servcheck_processes');
+$timeout = db_fetch_cell_prepared("SELECT MAX(duration_trigger*attempt)
+ FROM plugin_servcheck_test
+ WHERE
+ $sql_where",
+ $params);
-if (empty($max_processes)) {
- $max_processes = 8;
+if ($timeout > 0) {
+ $timeout += 2;
+} else {
+ read_config_option('servcheck_test_max_duration');
}
-if (cacti_sizeof($tests)) {
- $loop_count = 0;
-
- foreach ($tests as $test) {
- while (true) {
- $running = db_fetch_cell_prepared('SELECT COUNT(id)
- FROM processes
- WHERE tasktype = ?
- AND taskname = ?',
- ['servcheck', "child:$poller_id"]);
-
- if ($loop_count % 40 == 0) {
- servcheck_debug("There are $running processes");
- }
-
- if ($max_processes - $running > 0) {
- // The timeout is the number of attempts * the duration trigger or 5 seconds plus 5 seconds overhead
- $timeout = $test['attempt'] * ($test['duration_trigger'] == 0 ? 5 : $test['duration_trigger']) + 5;
+$use_processes = min($tests, $max_processes);
- if (!register_process_start('servcheck', $taskname, $test['id'], $timeout)) {
- cacti_log(sprintf('WARNING: Not Running Service Check %s it is still running', $test['name']), false, 'SERVCHECK');
- } else {
- servcheck_debug('Launching Service Check ' . $test['name']);
-
- $command = read_config_option('path_php_binary');
- $args = '-q "' . $config['base_path'] . '/plugins/servcheck/servcheck_process.php" --id=' . $test['id'] . ($debug ? ' --debug' : '');
+if ($tests > 0) {
+ for ($f = 1; $f <= $use_processes; $f++) {
+ if (!register_process_start('servcheck', $taskname, $f, $timeout)) {
+ cacti_log(sprintf('WARNING: Not Running Service Check %s it is still running', $test['name']), false, 'SERVCHECK');
+ } else {
+ servcheck_debug('Launching Servceck process ' . $f);
- exec_background($command, $args);
- }
+ $command = read_config_option('path_php_binary');
+ $args = '-q "' . $config['base_path'] . '/plugins/servcheck/servcheck_process.php" --process=' . $f . ($debug ? ' --debug' : '') . ($force ? ' --force' : '');
- break;
- } else {
- usleep(2000);
- }
-
- $loop_count++;
+ exec_background($command, $args);
}
}
} else {
@@ -248,7 +226,13 @@
$stat_search_ok = 0;
$stat_search_ko = 0;
-if (cacti_sizeof($tests)) {
+if ($tests > 0) {
+ $tests = db_fetch_assoc_prepared("SELECT *
+ FROM plugin_servcheck_test
+ WHERE
+ $sql_where",
+ $params);
+
foreach ($tests as $test) {
$test_last = db_fetch_row_prepared('SELECT result, result_search
FROM plugin_servcheck_log
@@ -362,7 +346,6 @@ function display_help() {
print PHP_EOL . 'usage: poller_servcheck.php [--debug] [--force]' . PHP_EOL . PHP_EOL;
print 'This binary will exec all the Service check child processes.' . PHP_EOL . PHP_EOL;
- print '--id - Run for a specific test' . PHP_EOL . PHP_EOL;
- print '--force - Force all the service checks to run now' . PHP_EOL . PHP_EOL;
+ print '--force - Force all the service checks to run now. Run even if the job is disabled or set to run less frequently than every poller cycle' . PHP_EOL . PHP_EOL;
print '--debug - Display verbose output during execution' . PHP_EOL . PHP_EOL;
}
diff --git a/servcheck_ca.php b/servcheck_ca.php
index b8cbdc0..2313d94 100644
--- a/servcheck_ca.php
+++ b/servcheck_ca.php
@@ -44,7 +44,7 @@
break;
case 'edit':
top_header();
- data_ca_edit();
+ servcheck_data_edit();
bottom_footer();
break;
@@ -169,7 +169,7 @@ function form_save() {
exit;
}
-function data_ca_edit() {
+function servcheck_data_edit() {
global $servcheck_ca_fields;
// ================= input validation =================
diff --git a/servcheck_credential.php b/servcheck_credential.php
index 9e70d56..aab0c66 100644
--- a/servcheck_credential.php
+++ b/servcheck_credential.php
@@ -45,7 +45,7 @@
break;
case 'edit':
top_header();
- data_credential_edit();
+ servcheck_data_edit();
bottom_footer();
break;
@@ -424,7 +424,7 @@ function form_save() {
exit;
}
-function data_credential_edit() {
+function servcheck_data_edit() {
global $servcheck_credential_fields, $servcheck_help_credential;
// ================= input validation =================
diff --git a/servcheck_process.php b/servcheck_process.php
index 5c81caa..ac96a64 100644
--- a/servcheck_process.php
+++ b/servcheck_process.php
@@ -62,12 +62,12 @@
$debug = false;
$force = false;
$test_id = 0;
+$process = 0;
$start = microtime(true);
+$max_mem = 0;
$poller_interval = read_config_option('poller_interval');
$poller_id = $config['poller_id'];
-$cert_expiry_days = read_config_option('servcheck_certificate_expiry_days');
-$new_notify_expire = false;
if (cacti_sizeof($parms)) {
foreach ($parms as $parameter) {
@@ -82,6 +82,10 @@
case '--id':
$test_id = intval($value);
+ break;
+ case '--process':
+ $process = intval($value);
+
break;
case '-d':
case '--debug':
@@ -93,7 +97,7 @@
case '-v':
display_version();
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ unregister_process('servcheck', "child:$poller_id");
exit;
case '--help':
@@ -101,7 +105,7 @@
case '-h':
display_help();
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ unregister_process('servcheck', "child:$poller_id");
exit;
case '--force':
@@ -114,425 +118,499 @@
print 'ERROR: Invalid Parameter ' . $parameter . PHP_EOL . PHP_EOL;
display_help();
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ unregister_process('servcheck', "child:$poller_id");
exit;
}
}
}
-if ($test_id <= 0) {
- print 'ERROR: You must specify a test id' . PHP_EOL;
+if ($test_id > 0 && $process > 0) {
+ print 'ERROR: Specify a test id or process number, not both' . PHP_EOL;
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ unregister_process('servcheck', "child:$poller_id");
exit(1);
}
-servcheck_check_debug();
+if ($test_id <= 0 && $process <= 0) {
+ print 'ERROR: You must specify a test id or process number' . PHP_EOL;
-$enabled = '';
+ unregister_process('servcheck', "child:$poller_id");
-if (!$force) {
- $enabled = 'AND enabled = "on"';
+ exit(1);
}
-$test = db_fetch_row_prepared('SELECT *, UNIX_TIMESTAMP(DATE_ADD(last_check,
- INTERVAL (? * how_often) SECOND)) AS next_run
- FROM plugin_servcheck_test
- WHERE id = ? ' . $enabled,
- [($poller_interval - 10), $test_id]);
+servcheck_check_debug();
-if (!cacti_sizeof($test)) {
- print 'ERROR: Test not Found!' . PHP_EOL;
+$max_processes = read_config_option('servcheck_processes');
- unregister_process('servcheck', "child:$poller_id", $test_id);
+if (empty($max_processes)) {
+ $max_processes = 8;
+}
- exit(1);
+$params = [];
+$params[] = $poller_id;
+$sql_where = 'poller_id = ? ';
+
+if (!$force) {
+ $sql_where .= 'AND enabled = "on" ';
}
-$poller = db_fetch_cell_prepared('SELECT * FROM poller WHERE id = ?',
- [$test['poller_id']]);
+$tests = db_fetch_cell_prepared('SELECT count(*)
+ FROM plugin_servcheck_test
+ WHERE ' . $sql_where,
+ $params);
-if ($poller == false) {
- print 'Selected poller not found, changing to poller 1' . PHP_EOL;
+$use_processes = min($tests, $max_processes);
- db_execute_prepared('UPDATE plugin_servcheck_test
- SET poller_id = 1
- WHERE id = ?',
- [$test['poller_id']]);
-}
+if ($process > 0) {
+ if ($process > $use_processes) {
+ print 'ERROR: Process number is bigger than max. servcheck process' . PHP_EOL;
-$logs = db_fetch_cell_prepared('SELECT COUNT(*)
- FROM plugin_servcheck_log
- WHERE test_id = ?',
- [$test['id']]);
+ unregister_process('servcheck', "child:$poller_id", $process);
-if ($logs > 0 && $test['next_run'] > time() && !$force) {
- servcheck_debug('INFO: Test "' . $test['name'] . '" skipped. Not the right time to run the test.');
+ exit(1);
+ } else {
+ $x = $process - 1;
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ $baseSize = intdiv($tests, $use_processes);
+ $remainder = $tests % $use_processes;
- exit(0);
-}
+ $extraBefore = min($x, $remainder);
-if (api_plugin_is_enabled('maint')) {
- require_once($config['base_path'] . '/plugins/maint/functions.php');
-}
+ $length = $baseSize + ($x < $remainder ? 1 : 0);
+ $offset = $x * $baseSize + $extraBefore;
-if (function_exists('plugin_maint_check_servcheck_test')) {
- if (plugin_maint_check_servcheck_test($test_id)) {
- servcheck_debug('Maintenance schedule active, skipped.');
+ array_unshift($params, ($poller_interval - 10));
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ $tests = db_fetch_assoc_prepared("SELECT *, UNIX_TIMESTAMP(DATE_ADD(last_check,
+ INTERVAL (? * how_often) SECOND)) AS next_run
+ FROM plugin_servcheck_test
+ WHERE $sql_where
+ LIMIT $offset, $length",
+ $params);
- exit(0);
+ print "Process: $process, offset: $offset, length: $length" . PHP_EOL;
}
}
-$test['days_left'] = 0;
-$test['duration'] = false;
+if ($test_id > 0) {
+ $sql_where .= 'AND id = ?';
+ $params[] = $test_id;
+ array_unshift($params, ($poller_interval - 10));
-// try it three times. First valid result skips next attempts
-$x = 0;
-$results = [];
+ $tests = db_fetch_assoc_prepared("SELECT *, UNIX_TIMESTAMP(DATE_ADD(last_check,
+ INTERVAL (? * how_often) SECOND)) AS next_run
+ FROM plugin_servcheck_test
+ WHERE $sql_where",
+ $params);
+}
-[$category, $service] = explode('_', $test['type']);
+if (!cacti_sizeof($tests)) {
+ print 'ERROR: Test/tests not Found!' . PHP_EOL;
-servcheck_debug('Category: ' . $category);
-servcheck_debug('Service: ' . $service);
+ unregister_process('servcheck', "child:$poller_id", $process);
-while ($x < $test['attempt']) {
- $x++;
+ exit(1);
+}
- servcheck_debug('Service Check attempt ' . $x);
+foreach ($tests as $test) {
+ $max_mem = memory_get_peak_usage(true);
- if (!function_exists('curl_init') && ($category == 'web' || $category == 'smb' || $category == 'ldap' ||
- $category == 'ftp' || $category == 'mqtt' || $category == 'rest' || $service == 'doh')) {
- print 'FATAL: You must install php-curl to use this test' . PHP_EOL;
+ if (function_exists('memory_reset_peak_usage')) {
+ memory_reset_peak_usage();
+ }
- servcheck_debug('Test ' . $test['id'] . ' requires php-curl library');
+ servcheck_debug(str_pad('Starting test ' . $test['name'], 10));
+ servcheck_run_test($test, $force);
+}
- $results['result'] = 'error';
- $results['curl'] = false;
- $results['error'] = 'missing php-curl library';
- $results['result_search'] = 'not tested';
- $results['start'] = microtime(true);
- $results['duration'] = 0;
- $results['data'] = '';
+unregister_process('servcheck', "child:$poller_id", $process);
- continue;
- }
+$rusage = getrusage();
- switch ($category) {
- case 'web':
- case 'ldap':
- case 'smb':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_curl.php');
- $results = curl_try($test);
+$end = microtime(true);
+$stats = sprintf('Time:%.2f, Stats:%s/%s, Down triggered:%s, Duration triggered:%s, Memory:%s MB, CPUuser:%.2f CPUsystem:%.2f',
+ $end - $start,
+ $test['stats_ok'],
+ $test['stats_bad'],
+ ($test['triggered'] == 0 ? 'No' : 'Yes'),
+ ($test['triggered_duration'] == 0 ? 'No' : 'Yes'),
+ $max_mem / 1024 / 1024,
+ $rusage['ru_utime.tv_sec'] + $rusage['ru_utime.tv_usec'] / 1E6,
+ $rusage['ru_stime.tv_sec'] + $rusage['ru_stime.tv_usec'] / 1E6);
- break;
- case 'mail':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_mail.php');
- $results = mail_try($test);
+servcheck_debug($stats);
- break;
- case 'mqtt':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_mqtt.php');
- $results = mqtt_try($test);
+function servcheck_run_test($test, $force) {
+ global $config;
- break;
- case 'dns':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_dns.php');
+ $usage_start = getrusage();
- if ($service == 'doh') {
- $results = doh_try($test);
- } else {
- $results = dns_try($test);
- }
+ $cert_expiry_days = read_config_option('servcheck_certificate_expiry_days');
+ $test['new_notify_expire'] = false;
- break;
- case 'rest':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_restapi.php');
- $results = restapi_try($test);
+ $poller = db_fetch_cell_prepared('SELECT * FROM poller WHERE id = ?',
+ [$test['poller_id']]);
- break;
- case 'snmp':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_snmp.php');
- $results = snmp_try($test);
+ if ($poller == false) {
+ print 'Selected poller not found, changing to poller 1' . PHP_EOL;
- break;
- case 'ssh':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_ssh.php');
- $results = ssh_try($test);
+ db_execute_prepared('UPDATE plugin_servcheck_test
+ SET poller_id = 1
+ WHERE id = ?',
+ [$test['poller_id']]);
+ }
- break;
- case 'ftp':
- require_once($config['base_path'] . '/plugins/servcheck/includes/test_ftp.php');
- $results = ftp_try($test);
+ $logs = db_fetch_cell_prepared('SELECT COUNT(*)
+ FROM plugin_servcheck_log
+ WHERE test_id = ?',
+ [$test['id']]);
- break;
+ if ($logs > 0 && $test['next_run'] > time() && !$force) {
+ servcheck_debug('INFO: Test "' . $test['name'] . '" skipped. Not the right time to run the test.');
+
+ return false;
}
- $results['duration'] = round(microtime(true) - $results['start'], 4);
+ if (api_plugin_is_enabled('maint')) {
+ require_once($config['base_path'] . '/plugins/maint/functions.php');
+ }
- if ($results['result'] == 'ok') {
- break;
- } else {
- servcheck_debug('Attempt ' . $x . ' was unsuccessful');
- servcheck_debug('Result: ' . clean_up_lines(var_export($results, true)));
+ if (function_exists('plugin_maint_check_servcheck_test')) {
+ if (plugin_maint_check_servcheck_test($test['id'])) {
+ servcheck_debug('Maintenance schedule active, skipped.');
+
+ return false;
+ }
}
- servcheck_debug('Sleeping 1 second');
+ $test['days_left'] = 0;
+ $test['duration'] = false;
- sleep(1);
-}
+ // try it three times. First valid result skips next attempts
+ $x = 0;
+ $results = [];
-$results['x'] = $x;
+ [$category, $service] = explode('_', $test['type']);
-if (cacti_sizeof($results) == 0) {
- servcheck_debug('Unknown error for test ' . $test['id']);
+ servcheck_debug('Category: ' . $category);
+ servcheck_debug('Service: ' . $service);
- unregister_process('servcheck', "child:$poller_id", $test_id);
+ while ($x < $test['attempt']) {
+ $x++;
- exit('Unknown error for test ' . $test['id']);
-}
+ servcheck_debug('Service Check attempt ' . $x);
-$results['time'] = time();
-$test['expiry_date'] = null;
+ if (!function_exists('curl_init') && ($category == 'web' || $category == 'smb' || $category == 'ldap' ||
+ $category == 'ftp' || $category == 'mqtt' || $category == 'rest' || $service == 'doh')) {
+ print 'FATAL: You must install php-curl to use this test' . PHP_EOL;
-if ($results['result'] == 'ok' && $test['certexpirenotify']) {
- if (isset($results['options']['certinfo'][0])) { // curl
- servcheck_debug('Returned certificate info: ' . clean_up_lines(var_export($results['options']['certinfo'], true)));
- $parsed = date_parse_from_format('M j H:i:s Y e', $results['options']['certinfo'][0]['Expire date']);
- // Prepare to retrieve the local expiry date of certificate instead of UTC date
- $dt = new DateTime(
- "{$parsed['year']}-{$parsed['month']}-{$parsed['day']} {$parsed['hour']}:{$parsed['minute']}:{$parsed['second']}",
- new DateTimeZone('UTC')
- );
+ servcheck_debug('Test ' . $test['id'] . ' requires php-curl library');
- $local_tz = date_default_timezone_get();
+ $results['result'] = 'error';
+ $results['curl'] = false;
+ $results['error'] = 'missing php-curl library';
+ $results['result_search'] = 'not tested';
+ $results['start'] = microtime(true);
+ $results['duration'] = 0;
+ $results['data'] = '';
- if (empty($local_tz)) {
- $local_tz = 'UTC';
+ continue;
}
- $dt->setTimezone(new DateTimeZone($local_tz));
- $exp = $dt->getTimestamp();
- $test['days_left'] = round(($exp - time()) / 86400,1);
- $test['expiry_date'] = date(date_time_format(), $exp);
- } elseif (isset($results['cert_valid_to'])) {
- // only for log
- $test['days_left'] = round(($results['cert_valid_to'] - time()) / 86400,1);
- $test['expiry_date'] = date(date_time_format(), $results['cert_valid_to']);
- }
-}
+ switch ($category) {
+ case 'web':
+ case 'ldap':
+ case 'smb':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_curl.php');
+ $results = curl_try($test);
-$last_log = db_fetch_row_prepared('SELECT *
- FROM plugin_servcheck_log
- WHERE test_id = ? ORDER BY id DESC LIMIT 1',
- [$test['id']]);
+ break;
+ case 'mail':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_mail.php');
+ $results = mail_try($test);
-if (!$last_log) {
- $last_log['result'] = 'not yet';
- $last_log['result_search'] = 'not yet';
-}
+ break;
+ case 'mqtt':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_mqtt.php');
+ $results = mqtt_try($test);
-if ($results['result'] == 'ok') {
- $test['stats_ok'] += 1;
-} else {
- $test['stats_bad'] += 1;
-}
+ break;
+ case 'dns':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_dns.php');
-$test['notify_result'] = false;
-$test['notify_search'] = false;
-$test['notify_duration'] = false;
-$test['notify_certificate'] = false;
+ if ($service == 'doh') {
+ $results = doh_try($test);
+ } else {
+ $results = dns_try($test);
+ }
-servcheck_debug('Checking for triggerers');
+ break;
+ case 'rest':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_restapi.php');
+ $results = restapi_try($test);
-if ($last_log['result'] != $results['result'] || $results['result'] != 'ok') {
- servcheck_debug('Result changed, notification will be send');
+ break;
+ case 'snmp':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_snmp.php');
+ $results = snmp_try($test);
- if ($results['result'] != 'ok') {
- $test['failures']++;
+ break;
+ case 'ssh':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_ssh.php');
+ $results = ssh_try($test);
- if ($test['failures'] >= $test['downtrigger'] && $test['triggered'] == 0) {
- $test['notify_result'] = true;
- $test['triggered'] = 1;
+ break;
+ case 'ftp':
+ require_once($config['base_path'] . '/plugins/servcheck/includes/test_ftp.php');
+ $results = ftp_try($test);
+
+ break;
}
- }
- if ($results['result'] == 'ok') {
- if ($test['triggered'] == 1) {
- $test['notify_result'] = true;
+ $results['duration'] = round(microtime(true) - $results['start'], 4);
+
+ if ($results['result'] == 'ok') {
+ break;
+ } else {
+ servcheck_debug('Attempt ' . $x . ' was unsuccessful');
+ servcheck_debug('Result: ' . clean_up_lines(var_export($results, true)));
}
- $test['triggered'] = 0;
- $test['failures'] = 0;
+ servcheck_debug('Sleeping 1 second');
+
+ sleep(1);
}
-} else { // only for stats, without notification
- if ($results['result'] != 'ok') {
- $test['failures']++;
- if ($test['failures'] >= $test['downtrigger']) {
- $test['triggered'] = 1;
- }
- } else {
- $test['triggered'] = 0;
- $test['failures'] = 0;
+ $results['x'] = $x;
+
+ if (cacti_sizeof($results) == 0) {
+ servcheck_debug('Unknown error for test ' . $test['id']);
+
+ return false;
}
-}
-// checks only if test passed or some search string exists
-if ($results['result_search'] != 'not tested' && $results['result'] == 'ok') {
- if ($last_log['result_search'] != $results['result_search']) {
- servcheck_debug('Search result changed, notification will be send');
- $test['notify_search'] = true;
+ $results['time'] = time();
+ $test['expiry_date'] = null;
+
+ if ($results['result'] == 'ok' && $test['certexpirenotify']) {
+ if (isset($results['options']['certinfo'][0])) { // curl
+ servcheck_debug('Returned certificate info: ' . clean_up_lines(var_export($results['options']['certinfo'], true)));
+ $parsed = date_parse_from_format('M j H:i:s Y e', $results['options']['certinfo'][0]['Expire date']);
+ // Prepare to retrieve the local expiry date of certificate instead of UTC date
+ $dt = new DateTime("{$parsed['year']}-{$parsed['month']}-{$parsed['day']} {$parsed['hour']}:{$parsed['minute']}:{$parsed['second']}",
+ new DateTimeZone('UTC')
+ );
+
+ $local_tz = date_default_timezone_get();
+
+ if (empty($local_tz)) {
+ $local_tz = 'UTC';
+ }
+
+ $dt->setTimezone(new DateTimeZone($local_tz));
+ $exp = $dt->getTimestamp();
+ $test['days_left'] = round(($exp - time()) / 86400,1);
+ $test['expiry_date'] = date(date_time_format(), $exp);
+ } elseif (isset($results['cert_valid_to'])) {
+ // only for log
+ $test['days_left'] = round(($results['cert_valid_to'] - time()) / 86400,1);
+ $test['expiry_date'] = date(date_time_format(), $results['cert_valid_to']);
+ }
}
-}
-// check certificate expiry
-if ($test['certexpirenotify'] && $cert_expiry_days > 0 && $test['days_left'] < $cert_expiry_days && $results['result'] == 'ok') {
- // notify once per day
- $new_notify = db_fetch_cell_prepared('SELECT UNIX_TIMESTAMP(DATE_ADD(last_exp_notify, INTERVAL 1 DAY))
- FROM plugin_servcheck_test
- WHERE id = ?',
+ $last_log = db_fetch_row_prepared('SELECT *
+ FROM plugin_servcheck_log
+ WHERE test_id = ? ORDER BY id DESC LIMIT 1',
[$test['id']]);
- if ($new_notify < time()) {
- servcheck_debug('Certificate will expire soon (or is expired), will notify about expiration');
- $test['notify_certificate'] = true;
- $test['certificate_state'] = 'ko';
- $new_notify_expire = true;
+ if (!$last_log) {
+ $last_log['result'] = 'not yet';
+ $last_log['result_search'] = 'not yet';
+ }
+
+ if ($results['result'] == 'ok') {
+ $test['stats_ok'] += 1;
+ } else {
+ $test['stats_bad'] += 1;
}
-}
-// check renewed cert
-if ($test['certexpirenotify'] && $results['result'] == 'ok') {
- if (isset($last_log['cert_expire']) &&
- $last_log['cert_expire'] != '0000-00-00 00:00:00' && !is_null($last_log['cert_expire'])) {
- $days_before = round((strtotime($last_log['cert_expire']) - strtotime($last_log['last_check'])) / 86400,1);
+ $test['notify_result'] = false;
+ $test['notify_search'] = false;
+ $test['notify_duration'] = false;
+ $test['notify_certificate'] = false;
- if ($test['days_left'] > 0 && $test['days_left'] > $days_before) {
- if (!servcheck_summer_time_changed()) {
- servcheck_debug('Renewed or changed certificate, notification will be send');
+ servcheck_debug('Checking for triggerers');
- $test['notify_certificate'] = true;
- $test['certificate_state'] = 'new';
- } else {
- servcheck_debug('Renewed or changed certificate, but summer/winter time change detected. Skipping notification.');
+ if ($last_log['result'] != $results['result'] || $results['result'] != 'ok') {
+ servcheck_debug('Result changed, notification will be send');
+
+ if ($results['result'] != 'ok') {
+ $test['failures']++;
+
+ if ($test['failures'] >= $test['downtrigger'] && $test['triggered'] == 0) {
+ $test['notify_result'] = true;
+ $test['triggered'] = 1;
}
}
- }
-}
-// long duration
-if ($test['duration_trigger'] > 0 && $test['duration_count'] > 0 && $results['result'] == 'ok') {
- $test['durs'] = [];
+ if ($results['result'] == 'ok') {
+ if ($test['triggered'] == 1) {
+ $test['notify_result'] = true;
+ }
- if ($results['duration'] > $test['duration_trigger']) {
- $test['triggered_duration']++;
+ $test['triggered'] = 0;
+ $test['failures'] = 0;
+ }
+ } else { // only for stats, without notification
+ if ($results['result'] != 'ok') {
+ $test['failures']++;
+
+ if ($test['failures'] >= $test['downtrigger']) {
+ $test['triggered'] = 1;
+ }
+ } else {
+ $test['triggered'] = 0;
+ $test['failures'] = 0;
+ }
}
- $test['durs'][] = $results['duration'] . ' (' . date('Y-m-d H:i:s', $results['time']) . ')';
+ // checks only if test passed or some search string exists
+ if ($results['result_search'] != 'not tested' && $results['result'] == 'ok') {
+ if ($last_log['result_search'] != $results['result_search']) {
+ servcheck_debug('Search result changed, notification will be send');
+ $test['notify_search'] = true;
+ }
+ }
- if ($test['duration_count'] > 1) {
- $durations = db_fetch_assoc_prepared('SELECT duration, last_check, result
- FROM plugin_servcheck_log
- WHERE test_id = ?
- ORDER BY id DESC LIMIT ' . ($test['duration_count'] - 1),
+ // check certificate expiry
+ if ($test['certexpirenotify'] && $cert_expiry_days > 0 && $test['days_left'] < $cert_expiry_days && $results['result'] == 'ok') {
+ // notify once per day
+ $new_notify = db_fetch_cell_prepared('SELECT UNIX_TIMESTAMP(DATE_ADD(last_exp_notify, INTERVAL 1 DAY))
+ FROM plugin_servcheck_test
+ WHERE id = ?',
[$test['id']]);
- foreach ($durations as $d) {
- $test['durs'][] = $d['duration'] . ' (' . $d['last_check'] . ')';
+ if ($new_notify < time()) {
+ servcheck_debug('Certificate will expire soon (or is expired), will notify about expiration');
+ $test['notify_certificate'] = true;
+ $test['certificate_state'] = 'ko';
+ $test['new_notify_expire'] = true;
}
}
- if ($test['triggered_duration'] == $test['duration_count']) {
- servcheck_debug('Long duration detected, sending notification');
+ // check renewed cert
+ if ($test['certexpirenotify'] && $results['result'] == 'ok') {
+ if (isset($last_log['cert_expire']) &&
+ $last_log['cert_expire'] != '0000-00-00 00:00:00' && !is_null($last_log['cert_expire'])) {
+ $days_before = round((strtotime($last_log['cert_expire']) - strtotime($last_log['last_check'])) / 86400,1);
- $test['notify_duration'] = true;
- $test['duration_state'] = 'ko';
- $test['triggered_duration']++;
- } elseif ($test['triggered_duration'] > $test['duration_count']) {
- servcheck_debug('Long duration issue continue');
+ if ($test['days_left'] > 0 && $test['days_left'] > $days_before) {
+ if (!servcheck_summer_time_changed()) {
+ servcheck_debug('Renewed or changed certificate, notification will be send');
- $test['triggered_duration']++;
+ $test['notify_certificate'] = true;
+ $test['certificate_state'] = 'new';
+ } else {
+ servcheck_debug('Renewed or changed certificate, but summer/winter time change detected. Skipping notification.');
+ }
+ }
+ }
}
- if ($results['duration'] < $test['duration_trigger'] && $test['triggered_duration'] >= $test['duration_count']) {
- servcheck_debug('Normal duration detected, sending notification');
+ // long duration
+ if ($test['duration_trigger'] > 0 && $test['duration_count'] > 0 && $results['result'] == 'ok') {
+ $test['durs'] = [];
- $test['notify_duration'] = true;
- $test['duration_state'] = 'ok';
- $test['triggered_duration'] = 0;
- }
-}
+ if ($results['duration'] > $test['duration_trigger']) {
+ $test['triggered_duration']++;
+ }
-if ($test['notify_result'] || $test['notify_search'] || $test['notify_duration'] || $test['notify_certificate']) {
- if (read_config_option('servcheck_disable_notification') == 'on') {
- cacti_log('Notifications are disabled, notification will not send for test ' . $test['name'], false, 'SERVCHECK');
- servcheck_debug('Notification disabled globally');
- } else {
- if ($test['notify'] != '') {
- servcheck_debug('Time to send email');
- plugin_servcheck_send_notification($results, $test, $last_log);
- } else {
- servcheck_debug('Time to send email, but email notification for this test is disabled');
+ $test['durs'][] = $results['duration'] . ' (' . date('Y-m-d H:i:s', $results['time']) . ')';
+
+ if ($test['duration_count'] > 1) {
+ $durations = db_fetch_assoc_prepared('SELECT duration, last_check, result
+ FROM plugin_servcheck_log
+ WHERE test_id = ?
+ ORDER BY id DESC LIMIT ' . ($test['duration_count'] - 1),
+ [$test['id']]);
+
+ foreach ($durations as $d) {
+ $test['durs'][] = $d['duration'] . ' (' . $d['last_check'] . ')';
+ }
}
- }
- $command = read_config_option('servcheck_change_command');
- $command_enable = read_config_option('servcheck_enable_scripts');
+ if ($test['triggered_duration'] == $test['duration_count']) {
+ servcheck_debug('Long duration detected, sending notification');
- if ($command_enable && $command != '' && $test['run_script'] == 'on') {
- servcheck_debug('Time to run command');
+ $test['notify_duration'] = true;
+ $test['duration_state'] = 'ko';
+ $test['triggered_duration']++;
+ } elseif ($test['triggered_duration'] > $test['duration_count']) {
+ servcheck_debug('Long duration issue continue');
- putenv('SERVCHECK_TEST_NAME=' . $test['name']);
- putenv('SERVCHECK_EXTERNAL_ID=' . $test['external_id']);
- putenv('SERVCHECK_TEST_TYPE=' . $test['type']);
- putenv('SERVCHECK_POLLER=' . $test['poller_id']);
- putenv('SERVCHECK_RESULT=' . $results['result']);
- putenv('SERVCHECK_RESULT_SEARCH=' . $results['result_search']);
- putenv('SERVCHECK_CERTIFICATE_EXPIRATION=' . (isset($test['expiry_date']) ? $test['expiry_date'] : 'Not tested or unknown '));
+ $test['triggered_duration']++;
+ }
- if (file_exists($command) && is_executable($command)) {
- $output = [];
- $return = 0;
+ if ($results['duration'] < $test['duration_trigger'] && $test['triggered_duration'] >= $test['duration_count']) {
+ servcheck_debug('Normal duration detected, sending notification');
- exec($command, $output, $return);
+ $test['notify_duration'] = true;
+ $test['duration_state'] = 'ok';
+ $test['triggered_duration'] = 0;
+ }
+ }
- cacti_log('Servcheck Command for test[' . $test['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'SERVCHECK');
+ if ($test['notify_result'] || $test['notify_search'] || $test['notify_duration'] || $test['notify_certificate']) {
+ if (read_config_option('servcheck_disable_notification') == 'on') {
+ cacti_log('Notifications are disabled, notification will not send for test ' . $test['name'], false, 'SERVCHECK');
+ servcheck_debug('Notification disabled globally');
} else {
- cacti_log('WARNING: Servcheck Command for test[' . $test['id'] . '] Command[' . $command . '] Is either Not found or Not executable!', false, 'SERVCHECK');
+ if ($test['notify'] != '') {
+ servcheck_debug('Time to send email');
+ plugin_servcheck_send_notification($results, $test, $last_log);
+ } else {
+ servcheck_debug('Time to send email, but email notification for this test is disabled');
+ }
}
- }
-} else {
- servcheck_debug('Nothing triggered');
-}
-$rusage = getrusage();
-update_statistics($test, $results, $new_notify_expire, $rusage);
+ $command = read_config_option('servcheck_change_command');
+ $command_enable = read_config_option('servcheck_enable_scripts');
-unregister_process('servcheck', "child:$poller_id", $test_id);
+ if ($command_enable && $command != '' && $test['run_script'] == 'on') {
+ servcheck_debug('Time to run command');
-$end = microtime(true);
-$stats = sprintf('Time:%.2f, Stats:%s/%s, Down triggered:%s, Duration triggered:%s, Memory:%s MB, CPUuser:%.2f CPUsystem:%.2f',
- $end - $start,
- $test['stats_ok'],
- $test['stats_bad'],
- ($test['triggered'] == 0 ? 'No' : 'Yes'),
- ($test['triggered_duration'] == 0 ? 'No' : 'Yes'),
- memory_get_peak_usage(true) / 1024 / 1024,
- $rusage['ru_utime.tv_sec'] + $rusage['ru_utime.tv_usec'] / 1E6,
- $rusage['ru_stime.tv_sec'] + $rusage['ru_stime.tv_usec'] / 1E6);
+ putenv('SERVCHECK_TEST_NAME=' . $test['name']);
+ putenv('SERVCHECK_EXTERNAL_ID=' . $test['external_id']);
+ putenv('SERVCHECK_TEST_TYPE=' . $test['type']);
+ putenv('SERVCHECK_POLLER=' . $test['poller_id']);
+ putenv('SERVCHECK_RESULT=' . $results['result']);
+ putenv('SERVCHECK_RESULT_SEARCH=' . $results['result_search']);
+ putenv('SERVCHECK_CERTIFICATE_EXPIRATION=' . (isset($test['expiry_date']) ? $test['expiry_date'] : 'Not tested or unknown '));
-servcheck_debug($stats);
+ if (file_exists($command) && is_executable($command)) {
+ $output = [];
+ $return = 0;
+
+ exec($command, $output, $return);
+
+ cacti_log('Servcheck Command for test[' . $test['id'] . '] Command[' . $command . '] ExitStatus[' . $return . '] Output[' . implode(' ', $output) . ']', false, 'SERVCHECK');
+ } else {
+ cacti_log('WARNING: Servcheck Command for test[' . $test['id'] . '] Command[' . $command . '] Is either Not found or Not executable!', false, 'SERVCHECK');
+ }
+ }
+ } else {
+ servcheck_debug('Nothing triggered');
+ }
-function update_statistics(&$test, &$results, $new_notify_expire, $rusage) {
servcheck_debug('Updating Statistics');
+ $usage_end = getrusage();
+ $user_cpu = ($usage_end['ru_utime.tv_sec'] + $usage_end['ru_utime.tv_usec']) - ($usage_start['ru_utime.tv_sec'] + $usage_start['ru_utime.tv_usec']);
+ $sys_cpu = ($usage_end['ru_stime.tv_sec'] + $usage_end['ru_stime.tv_usec']) - ($usage_start['ru_stime.tv_sec'] + $usage_start['ru_stime.tv_usec']);
+
if ($results['curl']) {
if (!isset($results['curl_return'])) {
$results['curl_return'] = 'N/A';
@@ -562,14 +640,14 @@ function update_statistics(&$test, &$results, $new_notify_expire, $rusage) {
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[$test['id'], $results['duration'], date('Y-m-d H:i:s', $results['time']), $save_exp,
$results['result'], $results['error'], $results['result_search'], $curl, $results['x'],
- $rusage['ru_utime.tv_sec'] + $rusage['ru_utime.tv_usec'] / 1E6,
- $rusage['ru_stime.tv_sec'] + $rusage['ru_stime.tv_usec'] / 1E6,
+ $user_cpu / 1E6,
+ $sys_cpu / 1E6,
memory_get_peak_usage(true) / 1024 / 1024,
strlen($results['data'])
]
);
- if ($new_notify_expire) {
+ if ($test['new_notify_expire']) {
$exp_notify = date(date_time_format());
} else {
$exp_notify = db_fetch_cell_prepared('SELECT last_exp_notify
@@ -588,7 +666,7 @@ function update_statistics(&$test, &$results, $new_notify_expire, $rusage) {
[$test['triggered'], $test['triggered_duration'], $test['failures'], date('Y-m-d H:i:s', $results['time']), $exp_notify,
$test['stats_ok'], $test['stats_bad'], $results['data'], $results['duration'],
$results['result'], $results['result_search'], $results['x'], $results['error'],
- $rusage['ru_utime.tv_sec'] + $rusage['ru_utime.tv_usec'] / 1E6, $rusage['ru_stime.tv_sec'] + $rusage['ru_stime.tv_usec'] / 1E6,
+ $user_cpu / 1E6, $sys_cpu / 1E6,
memory_get_peak_usage(true) / 1024 / 1024,
$test['id']
]
@@ -606,12 +684,13 @@ function update_statistics(&$test, &$results, $new_notify_expire, $rusage) {
}
function plugin_servcheck_send_notification($results, $test, $last_log) {
- global $httperrors, $cert_expiry_days;
+ global $httperrors;
$notify_list = [];
$notify_extra = [];
$notify_account = [];
- $local_tz = date_default_timezone_get();
+ $cert_expiry_days = read_config_option('servcheck_certificate_expiry_days');
+ $local_tz = date_default_timezone_get();
if (empty($local_tz)) {
$local_tz = 'UTC';
@@ -836,14 +915,14 @@ function plugin_servcheck_send_email($to, $subject, $message) {
* @return void
*/
function sig_handler($signo) {
- global $force, $poller_id, $test_id, $taskname;
+ global $force, $poller_id, $process, $taskname;
switch ($signo) {
case SIGTERM:
case SIGINT:
cacti_log("WARNING: Service Check Poller 'master' is shutting down by signal!", false, 'SERVCHECK');
- unregister_process('servcheck', "child:$poller_id", $test_id, getmypid());
+ unregister_process('servcheck', "child:$poller_id", $process, getmypid());
exit(1);
default:
@@ -873,9 +952,13 @@ function display_help() {
display_version();
print PHP_EOL;
- print 'usage: servcheck_process.php --id=N [--debug]' . PHP_EOL . PHP_EOL;
+ print 'usage: ' . PHP_EOL;
+ print 'servcheck_process.php --id=N [--debug] [--force]' . PHP_EOL . PHP_EOL;
+ print 'or: ' . PHP_EOL;
+ print 'servcheck_process.php --process=N [--debug] [--force]' . PHP_EOL . PHP_EOL;
print 'This binary will run the Service check for the Servcheck plugin.' . PHP_EOL . PHP_EOL;
- print '--id=N - The Test ID from the Servcheck database.' . PHP_EOL;
- print '--force - Run even if the job is disabled or set to run less frequently than every poller cycle' . PHP_EOL;
- print '--debug - Display verbose output during execution' . PHP_EOL . PHP_EOL;
+ print '--id=N - The Test ID from the Servcheck database.' . PHP_EOL;
+ print '--process=N - This process then processes (total number of tests/max. process) tests.' . PHP_EOL;
+ print '--force - Run even if the job is disabled or set to run less frequently than every poller cycle' . PHP_EOL;
+ print '--debug - Display verbose output during execution' . PHP_EOL . PHP_EOL;
}
diff --git a/servcheck_proxy.php b/servcheck_proxy.php
index 142abbf..13f0819 100644
--- a/servcheck_proxy.php
+++ b/servcheck_proxy.php
@@ -44,7 +44,7 @@
break;
case 'edit':
top_header();
- data_proxy_edit();
+ servcheck_data_edit();
bottom_footer();
break;
@@ -172,7 +172,7 @@ function form_save() {
exit;
}
-function data_proxy_edit() {
+function servcheck_data_edit() {
global $servcheck_proxy_fields;
// ================= input validation =================
diff --git a/servcheck_test.php b/servcheck_test.php
index a15c622..6ff202a 100644
--- a/servcheck_test.php
+++ b/servcheck_test.php
@@ -51,7 +51,7 @@
break;
case 'edit':
top_header();
- data_test_edit();
+ servcheck_data_edit();
bottom_footer();
break;
@@ -475,7 +475,7 @@ function purge_log_events($id) {
raise_message('test_log_purged', __('The Service Check history was purged for %s', $name, 'servcheck'), MESSAGE_LEVEL_INFO);
}
-function data_test_edit() {
+function servcheck_data_edit() {
global $servcheck_test_fields, $service_types, $servcheck_help_test;
// ================= input validation =================
@@ -937,14 +937,14 @@ function servcheck_show_history() {
}
if ($row['result'] == 'ok' && $row['result_search'] == 'not ok') {
- $style = 'background-color: ' . $servcheck_states['warning']['color'] . ';';
+ $style = 'servcheck_warning';
} elseif ($row['result'] == 'ok') {
- $style = 'background-color: ' . $servcheck_states['ok']['color'] . ';';
+ $style = 'servcheck_ok';
} else {
- $style = 'background-color: ' . $servcheck_states['error']['color'] . ';';
+ $style = 'servcheck_error';
}
- print "";
+ print " ";
form_selectable_cell($row['last_check'], $row['id']);
form_selectable_cell($row['name'], $row['id']);
@@ -1147,21 +1147,21 @@ function data_list() {
}
if ($row['enabled'] == '') {
- $style = 'background-color: ' . $servcheck_states['disabled']['color'] . ';';
+ $style = 'servcheck_disabled';
} elseif ($row['last_result'] == 'ok' && $row['triggered_duration'] >= $row['duration_count']) {
- $style = 'background-color: ' . $servcheck_states['duration']['color'] . ';';
+ $style = 'servcheck_duration';
$long_dur = true;
} elseif ($row['failures'] > 0 && $row['failures'] < $row['downtrigger']) {
- $style = 'background-color: ' . $servcheck_states['failing']['color'] . ';';
+ $style = 'servcheck_failing';
} elseif ($row['last_result'] == 'ok' && $row['last_result_search'] == 'not ok') {
- $style = 'background-color: ' . $servcheck_states['warning']['color'] . ';';
+ $style = 'servcheck_warning';
} elseif ($row['last_result'] == 'ok' && strtotime($row['last_check']) > 0) {
- $style = 'background-color: ' . $servcheck_states['ok']['color'] . ';';
+ $style = 'servcheck_ok';
} else {
- $style = 'background-color: ' . $servcheck_states['error']['color'] . ';';
+ $style = 'servcheck_error';
}
- print " ";
+ print " ";
print "
@@ -1241,7 +1241,7 @@ function servcheck_show_last_data() {
[get_filter_request_var('id')]);
print '' . __('Last returned data of test', 'servcheck') . ' ' . html_escape($result['name']) . ': ';
- print '' . html_escape($result['last_returned_data']) . ' ';
+ print '' . html_escape($result['last_returned_data']) . ' ';
}
function servcheck_filter() {
@@ -1254,7 +1254,7 @@ function servcheck_filter() {
set_page_refresh($refresh);
// When a row is selected, set the background-color as black and font color as white and when hovering over a row, the background is light grey
- servcheck_print_selectable_row_css();
+ // servcheck_print_selectable_row_css();
html_start_box(__('Servcheck Test Management', 'servcheck') , '100%', '', '3', 'center', htmlspecialchars(basename($_SERVER['PHP_SELF'])) . '?action=edit');
?>
@@ -1369,26 +1369,9 @@ function clearFilter() {
html_end_box();
}
-// Shared CSS for selectable table rows
-function servcheck_print_selectable_row_css() {
- print '';
-}
-
function servcheck_log_filter() {
global $item_rows;
- // When a row is selected, set the background-color as black and font color as white and when hovering over a row, the background is light grey
- servcheck_print_selectable_row_css();
-
html_start_box(__('Service Check History', 'servcheck') , '100%', '', '3', 'center', '');
?>
diff --git a/setup.php b/setup.php
index e28c4d4..02eb236 100644
--- a/setup.php
+++ b/setup.php
@@ -28,6 +28,7 @@ function plugin_servcheck_install() {
api_plugin_register_hook('servcheck', 'poller_bottom', 'plugin_servcheck_poller_bottom', 'setup.php');
api_plugin_register_hook('servcheck', 'replicate_out', 'servcheck_replicate_out', 'setup.php');
api_plugin_register_hook('servcheck', 'config_settings', 'servcheck_config_settings', 'setup.php');
+ api_plugin_register_hook('servcheck', 'page_head', 'servcheck_page_head', 'setup.php');
api_plugin_register_realm('servcheck', 'servcheck_test.php,servcheck_restapi.php,servcheck_credential.php,servcheck_curl_code.php,servcheck_proxy.php,servcheck_ca.php', __('Service Check Admin', 'servcheck'), 1);
@@ -702,5 +703,24 @@ function servcheck_config_settings() {
'365' => __('%d year', 1, 'servcheck'),
]
],
+ 'servcheck_test_max_duration' => [
+ 'friendly_name' => __('Maximum test duration in seconds', 'intropage'),
+ 'description' => __('The default value for tests where runtime testing is not enabled. If enabled, the max. duration is calculated as the duration threshold + 2 seconds.'),
+ 'method' => 'textbox',
+ 'max_length' => 2,
+ 'default' => '3',
+ ]
];
}
+
+function servcheck_page_head() {
+ global $config;
+
+ $selectedTheme = get_selected_theme();
+
+ print " ";
+
+ if (file_exists($config['base_path'] . '/plugins/servcheck/themes/' . $selectedTheme . '.css')) {
+ print " ";
+ }
+}
diff --git a/templates/README.md b/templates/README.md
new file mode 100644
index 0000000..132fa46
--- /dev/null
+++ b/templates/README.md
@@ -0,0 +1,10 @@
+
+## How to install and use Plugin Servcheck template
+
+Copy file servcheck.xml to /path/to/cacti/resource/script_server/
+
+Copy file ss_servcheck.php to /path/to/cacti/scripts/
+
+Import cacti_data_query_servcheck_plugin.xml from Console -> Import/Export -> Import Templates
+
+Edit your cacti device and add Associated Data Query Plugin Servcheck
\ No newline at end of file
diff --git a/templates/cacti_data_query_servcheck_plugin.xml b/templates/cacti_data_query_servcheck_plugin.xml
new file mode 100644
index 0000000..a96b920
--- /dev/null
+++ b/templates/cacti_data_query_servcheck_plugin.xml
@@ -0,0 +1,508 @@
+
+
+ Servcheck plugin
+ Test result graphs
+ <path_cacti>/resource/script_server/servcheck.xml
+ hash_030103332111d8b54ac8ce939af87a7eac0c06
+
+
+ hash_0001039ca59acaa7ac013e423d06d019e83ecc
+ Plugin servcheck test
+
+
+ result
+ hash_01010317fb3e01476bdbdc002b0ab2d4b804f3
+ hash_0801036d4514586cb5f1cf1873b3bb3a3fca79
+
+
+ duration
+ hash_01010317fb3e01476bdbdc002b0ab2d4b804f3
+ hash_080103c020046831f9c020c998db16fa523add
+
+
+ attempt
+ hash_01010317fb3e01476bdbdc002b0ab2d4b804f3
+ hash_0801033c32526b540ff2a720013c4f5d4825af
+
+
+
+
+
+
+
+
+
+
+ Get Script Server Data (Indexed)
+ 6
+
+
+
+ Index Type
+
+
+
+ index_type
+ in
+ index_type
+
+
+ Index Value
+
+
+
+ index_value
+ in
+ index_value
+
+
+ Output Type ID
+
+
+
+ output_type
+ in
+ output_type
+
+
+ Output Value
+ on
+
+
+
+ out
+ output
+
+
+
+
+ Plugin servcheck test
+
+
+
+
+ Servcheck - |query_servcheck_name|
+
+ status/duration/attempt
+
+ 3
+
+ 200
+
+ 700
+
+ 1000
+
+
+
+ on
+
+ 2
+
+
+
+
+
+
+
+ U
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+ 0
+
+ 0
+
+
+
+
+
+
+
+
+
+ 0
+
+ 0
+
+
+
+ 7
+ hash_0801033c32526b540ff2a720013c4f5d4825af
+ 3090C7
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Attempt
+
+ 1.00
+
+ 0
+ 1
+
+
+ 9
+ hash_0801033c32526b540ff2a720013c4f5d4825af
+ 0
+ FF
+ 4
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Cur:
+
+ 1.00
+
+ 0
+ 2
+
+
+ 9
+ hash_0801033c32526b540ff2a720013c4f5d4825af
+ 0
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Avg:
+
+ 1.00
+
+ 0
+ 3
+
+
+ 9
+ hash_0801033c32526b540ff2a720013c4f5d4825af
+ 0
+ FF
+ 3
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Max:
+ on
+ 1.00
+
+ 0
+ 4
+
+
+ 4
+ hash_0801036d4514586cb5f1cf1873b3bb3a3fca79
+ 000000
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Result
+
+ 1.00
+
+ 0
+ 5
+
+
+ 9
+ hash_0801036d4514586cb5f1cf1873b3bb3a3fca79
+ 0
+ FF
+ 4
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Cur:
+
+ 1.00
+
+ 0
+ 6
+
+
+ 9
+ hash_0801036d4514586cb5f1cf1873b3bb3a3fca79
+ 0
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Avg:
+
+ 1.00
+
+ 0
+ 7
+
+
+ 9
+ hash_0801036d4514586cb5f1cf1873b3bb3a3fca79
+ 0
+ FF
+ 3
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Max:
+ on
+ 1.00
+
+ 0
+ 8
+
+
+ 7
+ hash_080103c020046831f9c020c998db16fa523add
+ F88017
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Duration
+
+ 1.00
+
+ 0
+ 9
+
+
+ 9
+ hash_080103c020046831f9c020c998db16fa523add
+ 0
+ FF
+ 4
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Cur:
+
+ 1.00
+
+ 0
+ 10
+
+
+ 9
+ hash_080103c020046831f9c020c998db16fa523add
+ 0
+ FF
+ 1
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Avg:
+
+ 1.00
+
+ 0
+ 11
+
+
+ 9
+ hash_080103c020046831f9c020c998db16fa523add
+ 0
+ FF
+ 3
+ 0
+ 0
+
+
+ hash_060103e9c43831e54eca8069317a2ce8c6f751
+
+ Max:
+ on
+ 1.00
+
+ 0
+ 12
+
+
+
+
+ Data Source [attempt]
+
+ task_item_id
+ hash_000103ec683d0cb195fd3444c9b1c80b6bf9a6|hash_0001039d02a6b567b56833fe0fc7c683cfe0e6|hash_00010306ae72f5066b11c6063dd9f8aa8f6e4f|hash_0001033bfee14bfc566855e0f7a0b886a713ad
+
+
+ Data Source [result]
+
+ task_item_id
+ hash_00010329624ca529da4696eb12a6097fd715ba|hash_0001038c01cf13eda2aa9bb29ed7f0a6f1deb1|hash_000103998f7dd8bf0200c6fb00d170dd6a4d9a|hash_000103dbc3fdef66a69c1f0c3d3211ebd46eed
+
+
+ Data Source [duration]
+
+ task_item_id
+ hash_0001038d6e2c3ffdb0c960e1f6a44f24c22e8b|hash_0001039f2676c9be786ae46fdd5bb531e9fdec|hash_0001032582b0b7a3c9ed6e543da962543112f1|hash_000103f2c87914348840926440532de468b960
+
+
+
+
+ Plugin Servcheck - test result
+
+
+ Servcheck - |query_servcheck_name|
+ hash_030103332111d8b54ac8ce939af87a7eac0c06
+
+ hash_2001039762df759b20fa02e03e4353e08f627c
+
+ 300
+
+ on
+
+
+
+
+ result
+
+ 0
+
+ U
+
+ 1
+
+ 600
+
+ 0
+
+
+
+ duration
+
+ 0
+
+ U
+
+ 1
+
+ 600
+
+ 0
+
+
+
+ attempt
+
+ 0
+
+ U
+
+ 1
+
+ 600
+
+ 0
+
+
+
+
+ hash_070103172b4b0eacee4948c6479f587b62e512
+ on
+
+
+
+ hash_07010330fb5d5bcf3d66bb5abe88596f357c26
+ on
+
+
+
+ hash_07010331112c85ae4ff821d3b288336288818c
+ on
+
+
+
+
+
+ 5 Minute Collection
+ 300
+ 600
+ 0.5
+ on
+ 1|3
+
+
+ Daily (5 Minute Average)
+ 1
+ 600
+ 172800
+
+
+ Weekly (30 Minute Average)
+ 6
+ 700
+ 1209600
+
+
+ Monthly (2 Hour Average)
+ 24
+ 775
+ 5237568
+
+
+ Yearly (1 Day Average)
+ 288
+ 797
+ 63072000
+
+
+
+
+ Normal
+ %8.2lf %s
+
+
\ No newline at end of file
diff --git a/templates/servcheck.xml b/templates/servcheck.xml
new file mode 100644
index 0000000..660f71a
--- /dev/null
+++ b/templates/servcheck.xml
@@ -0,0 +1,42 @@
+
+ Servcheck Data Query
+ |path_cacti|/scripts/ss_servcheck.php
+ ss_servcheck
+ php
+
+ index
+ query
+ get
+ !
+ servcheck_id
+ numeric
+ Check#|chosen_order_field|
+
+
+
+ Test Id
+ input
+ servcheck_id
+
+
+ Test Name
+ input
+ servcheck_name
+
+
+ Attemp
+ output
+ attempt
+
+
+ Duration
+ output
+ duration
+
+
+ Result
+ output
+ result
+
+
+
\ No newline at end of file
diff --git a/templates/ss_servcheck.php b/templates/ss_servcheck.php
new file mode 100755
index 0000000..48302b5
--- /dev/null
+++ b/templates/ss_servcheck.php
@@ -0,0 +1,106 @@
+#!/usr/bin/env php
+