Skip to content

Commit b0a43c0

Browse files
authored
add more info sections (#2707)
* add more info sections
1 parent cc002ba commit b0a43c0

2 files changed

Lines changed: 262 additions & 38 deletions

File tree

web/maintenance/systeminfo.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ <h1>Systeminformationen</h1>
193193
let chartsHtml = '<div class="card-container">';
194194
for (const key in history) {
195195
if (!Object.hasOwn(history, key)) continue;
196-
if (!chartSections.includes(key)) continue;
196+
if (!chartSections.some(section => key.startsWith(section))) continue;
197197
const value = history[key];
198198
// Prüfe, ob es sich um mehrere Reihen handelt (Objekt mit value/unit) oder Array
199199
if (Array.isArray(value)) {
@@ -248,7 +248,7 @@ <h2>${key}</h2>
248248
// Diagramme zeichnen
249249
for (const key in history) {
250250
if (!Object.hasOwn(history, key)) continue;
251-
if (!chartSections.includes(key)) continue;
251+
if (!chartSections.some(section => key.startsWith(section))) continue;
252252
const value = history[key];
253253
if (Array.isArray(value)) {
254254
const canvas = document.getElementById(`chart_${key}`);

web/maintenance/systeminfo_api.php

Lines changed: 260 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,231 @@
99
'mosquitto_local.service'
1010
];
1111

12+
$numTopProcesses = 10;
13+
14+
function getHardwareInfo()
15+
{
16+
// Board-Name
17+
$board = trim(@shell_exec("cat /sys/class/dmi/id/board_name 2>/dev/null"));
18+
if ($board === '') {
19+
$board = trim(@shell_exec("cat /proc/device-tree/model 2>/dev/null"));
20+
}
21+
if ($board === '') {
22+
$board = 'unbekannt';
23+
}
24+
25+
// CPU-Kerne
26+
$cpuCores = (int)@shell_exec('nproc') ?: 1;
27+
28+
// CPU-Temperatur (verschiedene Pfade möglich)
29+
$temp = null;
30+
$paths = [
31+
'/sys/class/thermal/thermal_zone0/temp',
32+
'/sys/devices/virtual/thermal/thermal_zone0/temp'
33+
];
34+
foreach ($paths as $path) {
35+
if (is_readable($path)) {
36+
$raw = trim(file_get_contents($path));
37+
if (is_numeric($raw)) {
38+
// Wert meist in Milligrad
39+
$temp = round(((int)$raw) / 1000, 1);
40+
break;
41+
}
42+
}
43+
}
44+
if ($temp === null) {
45+
// Fallback: vcgencmd (z.B. Raspberry Pi)
46+
$vcgencmd = trim(@shell_exec('which vcgencmd'));
47+
if ($vcgencmd) {
48+
$out = trim(@shell_exec('vcgencmd measure_temp 2>/dev/null'));
49+
if (preg_match('/temp=([\d\.]+)/', $out, $m)) {
50+
$temp = (float)$m[1];
51+
}
52+
}
53+
}
54+
if ($temp === null) {
55+
$temp = 'unbekannt';
56+
}
57+
58+
// Uptime
59+
$uptime = 'unbekannt';
60+
if (is_readable('/proc/uptime')) {
61+
$uptimeSeconds = (float)file_get_contents('/proc/uptime');
62+
$days = floor($uptimeSeconds / 86400);
63+
$hours = floor(($uptimeSeconds % 86400) / 3600);
64+
$minutes = floor(($uptimeSeconds % 3600) / 60);
65+
$seconds = floor($uptimeSeconds % 60);
66+
$uptime = sprintf('%d Tage, %02d:%02d:%02d', $days, $hours, $minutes, $seconds);
67+
}
68+
69+
// Systemzeit
70+
$systemTime = date('d.m.Y, H:i:s');
71+
72+
return [
73+
'board' => [
74+
'value' => $board,
75+
'unit' => ''
76+
],
77+
'cpu_cores' => [
78+
'value' => $cpuCores,
79+
'unit' => ''
80+
],
81+
'cpu_temp' => [
82+
'value' => $temp,
83+
'unit' => is_numeric($temp) ? '°C' : ''
84+
],
85+
'uptime' => [
86+
'value' => $uptime,
87+
'unit' => ''
88+
],
89+
'system_time' => [
90+
'value' => $systemTime,
91+
'unit' => ''
92+
]
93+
];
94+
}
95+
96+
function getNetworkInfo()
97+
{
98+
$mac = 'unbekannt';
99+
$ip = 'unbekannt';
100+
$subnet = 'unbekannt';
101+
$gateway = 'unbekannt';
102+
$iface = null;
103+
104+
// Ermittle Gateway und zugehörige Schnittstelle
105+
$route = @shell_exec("ip route | awk '/default/ {print \$3, \$5; exit}'");
106+
if ($route) {
107+
list($gateway, $iface) = explode(' ', trim($route));
108+
}
109+
110+
if ($iface) {
111+
// MAC-Adresse mit ip-Befehl
112+
$macInfo = @shell_exec("ip link show $iface | awk '/link\\// {print \$2; exit}'");
113+
if ($macInfo) {
114+
$mac = trim($macInfo);
115+
}
116+
// IP und Subnetz
117+
$ipInfo = @shell_exec("ip -o -f inet addr show $iface | awk '{print \$4}'");
118+
if ($ipInfo) {
119+
$ipCidr = trim($ipInfo);
120+
if (strpos($ipCidr, '/') !== false) {
121+
list($ip, $cidr) = explode('/', $ipCidr);
122+
// Subnetz berechnen
123+
$subnet = long2ip(-1 << (32 - (int)$cidr));
124+
}
125+
}
126+
}
127+
128+
return [
129+
'interface' => [
130+
'value' => $iface ?? 'unbekannt',
131+
'unit' => ''
132+
],
133+
'mac' => [
134+
'value' => $mac,
135+
'unit' => ''
136+
],
137+
'ip' => [
138+
'value' => $ip,
139+
'unit' => ''
140+
],
141+
'subnet' => [
142+
'value' => $subnet,
143+
'unit' => ''
144+
],
145+
'gateway' => [
146+
'value' => $gateway,
147+
'unit' => ''
148+
]
149+
];
150+
}
151+
152+
function getSoftwareInfo()
153+
{
154+
$version = 'unbekannt';
155+
// $branch = 'unbekannt';
156+
$commit = 'unbekannt';
157+
158+
// Git-Verzeichnis bestimmen (eine Ebene höher als "web")
159+
$repoDir = dirname(__DIR__, 2);
160+
161+
// Lese Versionsdatei (eine Ebene höher)
162+
$versionFile = dirname(__DIR__, 1) . '/version';
163+
if (is_readable($versionFile)) {
164+
$version = trim(file_get_contents($versionFile));
165+
}
166+
167+
// // Ermittle aktuellen Git-Branch
168+
// $branchCmd = 'git -C ' . escapeshellarg($repoDir) . ' rev-parse --abbrev-ref HEAD 2>/dev/null';
169+
// $branchOut = trim(@shell_exec($branchCmd));
170+
// if ($branchOut !== '') {
171+
// $branch = $branchOut;
172+
// }
173+
174+
// Ermittle aktuellen Git-Commit
175+
$commitFile = dirname(__DIR__, 1) . '/lastcommit';
176+
if (is_readable($commitFile)) {
177+
$commit = trim(file_get_contents($commitFile));
178+
}
179+
180+
return [
181+
'version' => [
182+
'value' => $version,
183+
'unit' => ''
184+
],
185+
// 'git_branch' => [
186+
// 'value' => $branch,
187+
// 'unit' => ''
188+
// ],
189+
'git_commit' => [
190+
'value' => $commit,
191+
'unit' => ''
192+
]
193+
];
194+
}
195+
12196
function getCpuLoad()
13197
{
14198
$load = sys_getloadavg();
15-
$cpuCores = (int)@shell_exec('nproc') ?: 1; // Fallback auf 1 Kern, falls nproc nicht verfügbar
199+
// Rückgabe der 1, 5 und 15 Minuten Last
200+
201+
// Lese die CPU-Zeile aus /proc/stat
202+
$stat1 = explode(" ", preg_replace('!\s+!', ' ', trim(shell_exec("head -n1 /proc/stat"))));
203+
usleep(100000); // 100ms warten
204+
$stat2 = explode(" ", preg_replace('!\s+!', ' ', trim(shell_exec("head -n1 /proc/stat"))));
205+
206+
// user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice
207+
$fields = [1, 2, 3, 4, 5, 6, 7, 8];
208+
$cpu1 = $cpu2 = 0;
209+
foreach ($fields as $i) {
210+
$cpu1 += isset($stat1[$i]) ? (int)$stat1[$i] : 0;
211+
$cpu2 += isset($stat2[$i]) ? (int)$stat2[$i] : 0;
212+
}
213+
$idle1 = isset($stat1[4]) ? (int)$stat1[4] : 0;
214+
$idle2 = isset($stat2[4]) ? (int)$stat2[4] : 0;
215+
216+
$totalDiff = $cpu2 - $cpu1;
217+
$idleDiff = $idle2 - $idle1;
218+
219+
$cpuPercent = $totalDiff > 0 ? round((1 - ($idleDiff / $totalDiff)) * 100, 1) : 0;
16220

17221
return [
18-
// '1min' => [
19-
// 'value' => $load[0],
20-
// 'unit' => ''
21-
// ],
22-
'1min_percent' => [
23-
'value' => round(($load[0] / $cpuCores) * 100, 1),
222+
'used_percent' => [
223+
'value' => $cpuPercent,
24224
'unit' => '%'
25225
],
26-
// '5min' => [
27-
// 'value' => $load[1],
28-
// 'unit' => ''
29-
// ],
30-
'5min_percent' => [
31-
'value' => round(($load[1] / $cpuCores) * 100, 1),
32-
'unit' => '%'
226+
'load_1min' => [
227+
'value' => $load[0],
228+
'unit' => ''
33229
],
34-
// '15min' => [
35-
// 'value' => $load[2],
36-
// 'unit' => ''
37-
// ],
38-
'15min_percent' => [
39-
'value' => round(($load[2] / $cpuCores) * 100, 1),
40-
'unit' => '%'
230+
'load_5min' => [
231+
'value' => $load[1],
232+
'unit' => ''
233+
],
234+
'load_15min' => [
235+
'value' => $load[2],
236+
'unit' => ''
41237
]
42238
];
43239
}
@@ -77,30 +273,30 @@ function getMemoryUsage()
77273
return false;
78274
}
79275

80-
function getStorageUsage()
276+
function getPartitionUsage($path, $label)
81277
{
82-
$diskTotal = @disk_total_space("/");
83-
$diskFree = @disk_free_space("/");
278+
$diskTotal = @disk_total_space($path);
279+
$diskFree = @disk_free_space($path);
84280
if ($diskTotal === false || $diskFree === false) {
85281
return false;
86282
}
87283
$diskUsed = $diskTotal - $diskFree;
88284
return [
89-
'used_percent' => [
285+
$label . '_used_percent' => [
90286
'value' => round($diskUsed / $diskTotal * 100, 1),
91287
'unit' => '%'
92288
],
93-
'total' => [
94-
'value' => round($diskTotal / 1024 / 1024 / 1024, 2),
95-
'unit' => 'GB'
289+
$label . '_total' => [
290+
'value' => round($diskTotal / 1024 / 1024, 2),
291+
'unit' => 'MB'
96292
],
97-
'used' => [
98-
'value' => round($diskUsed / 1024 / 1024 / 1024, 2),
99-
'unit' => 'GB'
293+
$label . '_used' => [
294+
'value' => round($diskUsed / 1024 / 1024, 2),
295+
'unit' => 'MB'
100296
],
101-
'free' => [
102-
'value' => round($diskFree / 1024 / 1024 / 1024, 2),
103-
'unit' => 'GB'
297+
$label . '_free' => [
298+
'value' => round($diskFree / 1024 / 1024, 2),
299+
'unit' => 'MB'
104300
]
105301
];
106302
}
@@ -116,6 +312,28 @@ function getServiceStatus($services)
116312
return $result;
117313
}
118314

315+
function getTopCpuProcesses($limit)
316+
{
317+
// ps gibt: PID, Benutzer, CPU-Auslastung, Speicher, Befehl
318+
$cmd = "ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -n " . ($limit + 1);
319+
$output = [];
320+
exec($cmd, $output);
321+
322+
$result = [];
323+
// Erste Zeile ist die Überschrift
324+
for ($i = 1; $i < count($output); $i++) {
325+
// Spalten trennen (mehrere Leerzeichen)
326+
$cols = preg_split('/\s+/', trim($output[$i]), 5);
327+
if (count($cols) === 5) {
328+
$result[$cols[4] . ' (' . $cols[0] . ')'] = [
329+
'value' => (float)$cols[2],
330+
'unit' => '%'
331+
];
332+
}
333+
}
334+
return $result;
335+
}
336+
119337
// API-Handler
120338
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
121339
header('Content-Type: application/json');
@@ -158,10 +376,16 @@ function getServiceStatus($services)
158376
if (php_sapi_name() !== 'cli' && basename($_SERVER['SCRIPT_FILENAME']) === 'systeminfo_api.php') {
159377
header('Content-Type: application/json');
160378
echo json_encode([
379+
'hardwareInfo' => getHardwareInfo(),
380+
'networkInfo' => getNetworkInfo(),
381+
'softwareInfo' => getSoftwareInfo(),
161382
'cpuLoad' => getCpuLoad(),
162383
'memory' => getMemoryUsage(),
163-
'storage' => getStorageUsage(),
164-
'services' => getServiceStatus($serviceList)
384+
'top10CpuProcesses' => getTopCpuProcesses($numTopProcesses),
385+
'services' => getServiceStatus($serviceList),
386+
'storage (root)' => getPartitionUsage('/', 'root'),
387+
'storage (boot)' => getPartitionUsage('/boot', 'boot'),
388+
'storage (ramdisk)' => getPartitionUsage('/var/www/html/openWB/ramdisk', 'ramdisk'),
165389
]);
166390
exit;
167391
}

0 commit comments

Comments
 (0)