commit 3d50432ff438e250d8b1d44497668e43fee29265 Author: Wirlaburla Date: Wed Apr 3 22:08:54 2024 -0500 Initial commit diff --git a/banner.png b/banner.png new file mode 100644 index 0000000..733c4d6 Binary files /dev/null and b/banner.png differ diff --git a/data/config.php.example b/data/config.php.example new file mode 100755 index 0000000..8a21eaa --- /dev/null +++ b/data/config.php.example @@ -0,0 +1,61 @@ +array( + ## This will be the name of the service as displayed on the status page. + #'name'=>'Web Server', + + ## This will be the message displayed under the collapsable title. + #'message'=>'To be, or not to be.', + + ## The pid file of the service to check. If 'process' is also defined, + ## this will override its check. Make sure the runner has permissions + ## to read the file. + #'pidfile'=>'/run/nginx.pid', + + ## Icon to display alongside the service name. Path is relative to page. + ## You can also leave this blank for no icon. + #'icon'=>'http.png', + + ## Name of the process to query. This will search using pgrep. + #'process'=>'nginx', + + ## Hostname of the server to ping. This and 'ports' may be omitted if + ## you do not want to ping it. + #'hostname'=>'shakespear.lit', + + ## Array of ports to ping. If more than one port, the displayed ping will be averaged. Requires 'hostname' to function properly. + #'ports'=>array(80,443) + #) +); +?> \ No newline at end of file diff --git a/data/update.php b/data/update.php new file mode 100755 index 0000000..5e3dae4 --- /dev/null +++ b/data/update.php @@ -0,0 +1,136 @@ +errorCode() && $SQL->errorCode() !== '00000') { + die($SQL->errorCode()); + } + + $SQL->query('CREATE TABLE IF NOT EXISTS service_status(service TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, ping INTEGER, status INTEGER, PRIMARY KEY(service, timestamp))'); + + foreach($CONFIG['services'] as $id=>$data) { + $services[$id] = array( + 'name'=>$data['name'], + 'message'=>$data['message'] + ); + if (isset($data['icon'])) $services[$id]['icon'] = $data['icon']; + $timestamp = date('Y-m-d H:i:s'); + // Ping is in ms. Status is 0 if okay, +1 for each unreachable, and -1 if offline completely. + $ping = -1; $status = 0; + // Check for ports (with ping) + if (isset($data['ports'])) { + $pings = array(); $i = 0; + foreach ($data['ports'] as $port) { + $starttime = microtime(true); + if ($fp = fsockopen($data['hostname'],$port,$errno,$errstr,15)) { + $stoptime = microtime(true); + $newping = ($stoptime - $starttime) * 1000; + $pings[$i++] = $newping; + } else $status++; + } + if ($i == 1) + $ping = round($pings[0], 2); + else if ($i > 0 && ($ping_sum = array_sum($pings)) > 0) + $ping = round($ping_sum / $i, 2); + } + + // Check for PID (status) + if (isset($data['pidfile'])) { + if (!posix_getpgid(file_get_contents($data['pidfile']))) + $status = -1; + } + + // Check for process (status) + if (isset($data['process']) && !isset($data['pidfile'])) { + $otp; $rtn; + exec('pgrep -fl "'.$data['process'].'"', $otp, $rtn); + if ($rtn!=0) $status = -1; + } + + if ($stmt = $SQL->prepare('INSERT INTO service_status(service, timestamp, ping, status) VALUES (?, ?, ?, ?)')) { + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $timestamp); + $stmt->bindParam(3, $ping); + $stmt->bindParam(4, $status); + $stmt->execute(); + $stmt->closeCursor(); + } + + if ($stmt = $SQL->prepare('SELECT timestamp,ping,status FROM service_status WHERE service = ? ORDER BY timestamp DESC LIMIT ?')) { + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $CONFIG['max_slices']); + if ($stmt->execute()) { + $services[$id]['status'] = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + array_push($services[$id]['status'], $row); + } + } + $stmt->closeCursor(); + } + $services[$id]['status'] = array_reverse($services[$id]['status']); + } +?> + + + + <?=$CONFIG['page_name'];?> + '> + + '> + '> + + + + + + + +
+ + '; + echo ''; + if (!empty($service['message'])) { + echo '
'; + if (!empty($service['icon'])) + echo ' '; + echo $service['name'].''.$service['message'].'
'; + } else { + if (!empty($service['icon'])) + echo ' '; + echo ''.$service['name'].''; + } + echo ''; + echo ''; + foreach ($service['status'] as $slice) { + $cell_status; $bgclrstyle = ''; + $_time = date($CONFIG['timestamp_format'], strtotime($slice['timestamp'])); + $_ping = $slice['ping'].'ms'; + + if ($slice['status'] > 0 || ($slice['status'] == -1 && $slice['ping'] > 0)) { + $cell_status = 'partial'; + $bgclrstyle = sprintf("#%02x%02x%02x", 255, 128, 0); + } else if ($slice['status'] == -1) { + $cell_status = 'offline'; + $bgclrstyle = sprintf("#%02x%02x%02x", 255, 0, 0); + } else { + $cell_status = 'ok'; + $bgclrstyle = sprintf( + "#%02x%02x%02x", + $slice['ping']!=-1?max(0, min(255, round($slice['ping'])*2)):0, + max(0, min(255, 128+(round($slice['ping'])/2))), + 0 + ); + } + + echo ''; + } + echo ''."\n"; + } + ?> +
+
+ + \ No newline at end of file diff --git a/style.css b/style.css new file mode 100755 index 0000000..de5b449 --- /dev/null +++ b/style.css @@ -0,0 +1,28 @@ +body { + background: #d3d3d3; +} + +body > center > * { + max-width: 800px; +} +details { + text-align: left; +} +details > summary { + cursor: pointer; +} + +table { width: 100%; } +table.status { margin: 8px 0; } +table.status tr:not(.title) td { height: 16px; } +table.status tr:not(.title) td:hover:after { + content: attr(value); + position: absolute; + background-color: rgba(0,0,0,0.75); + border-radius: 8px; + color: white; + padding: 2px 4px; + margin: -58px -8px; + white-space: pre; + pointer-events: none; +} \ No newline at end of file