터치 패널 정리와 재부팅 원인 기록 보강
This commit is contained in:
1 parent
64510e8fe5
commit
11f27e5347
9 files changed
+488
-358
No files matched your search
+44
-10
@@ -191,18 +191,38 @@ function command_first_line(array $cmd, bool $root = false, int $timeout = 3): s
|
||||
function log_retention_status(): array
|
||||
{
|
||||
$journalDir = '/var/log/journal';
|
||||
$journalDisk = command_first_line(['/usr/bin/journalctl', '--disk-usage', '--no-pager'], false, 3);
|
||||
$journalBoots = command_first_line(['/usr/bin/bash', '-lc', 'journalctl --list-boots --no-pager 2>/dev/null | wc -l'], false, 3);
|
||||
$journalDisk = command_first_line(['/usr/bin/journalctl', '--disk-usage', '--no-pager'], true, 3);
|
||||
$journalBootResult = sh(['/usr/bin/journalctl', '--list-boots', '--no-pager'], true, 3);
|
||||
$journalBootLines = (int)$journalBootResult['code'] === 0
|
||||
? array_values(array_filter(
|
||||
preg_split('/\R/', trim((string)$journalBootResult['out'])) ?: [],
|
||||
static fn($line): bool => preg_match('/^\s*-?\d+\s+[0-9a-f]{32}\s+/i', (string)$line) === 1
|
||||
))
|
||||
: [];
|
||||
$pstoreActive = command_first_line(['/usr/bin/systemctl', 'is-active', 'control-pstore-collect.service'], false, 3) ?: 'inactive';
|
||||
$savedCrashFiles = glob('/var/log/pstore/*') ?: [];
|
||||
$controlCrashFiles = glob('/var/log/pstore/*') ?: [];
|
||||
$systemdCrashFiles = glob('/var/lib/systemd/pstore/*') ?: [];
|
||||
$savedCrashFiles = $controlCrashFiles !== [] ? $controlCrashFiles : $systemdCrashFiles;
|
||||
$pstoreFiles = glob('/sys/fs/pstore/*') ?: [];
|
||||
$bootEventPath = '/var/log/control/boot-events.jsonl';
|
||||
$bootEventLines = is_readable($bootEventPath)
|
||||
? (file($bootEventPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [])
|
||||
: [];
|
||||
$latestBootEvent = [];
|
||||
if ($bootEventLines !== []) {
|
||||
$decoded = json_decode((string)end($bootEventLines), true);
|
||||
if (is_array($decoded)) {
|
||||
$latestBootEvent = $decoded;
|
||||
}
|
||||
}
|
||||
$bootCaptureActive = $latestBootEvent !== [] ? 'active' : 'inactive';
|
||||
|
||||
return [
|
||||
'journal' => [
|
||||
'path' => $journalDir,
|
||||
'persistent' => is_dir($journalDir),
|
||||
'disk_usage' => $journalDisk ?: '-',
|
||||
'boot_count' => is_numeric(trim($journalBoots)) ? (int)trim($journalBoots) : null,
|
||||
'boot_count' => count($journalBootLines),
|
||||
'ok' => is_dir($journalDir),
|
||||
],
|
||||
'pstore' => [
|
||||
@@ -210,8 +230,17 @@ function log_retention_status(): array
|
||||
'collector_active' => $pstoreActive,
|
||||
'pending_files' => count($pstoreFiles),
|
||||
'saved_files' => count($savedCrashFiles),
|
||||
'systemd_saved_files' => count($systemdCrashFiles),
|
||||
'saved_path' => '/var/log/pstore',
|
||||
'ok' => is_dir('/sys/fs/pstore'),
|
||||
'systemd_path' => '/var/lib/systemd/pstore',
|
||||
'ok' => is_dir('/sys/fs/pstore') && is_dir('/var/lib/systemd/pstore'),
|
||||
],
|
||||
'boot_capture' => [
|
||||
'active' => $bootCaptureActive,
|
||||
'path' => $bootEventPath,
|
||||
'count' => count($bootEventLines),
|
||||
'latest' => $latestBootEvent,
|
||||
'ok' => $bootCaptureActive === 'active' && is_readable($bootEventPath),
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -3408,14 +3437,17 @@ function remember_lan_wol_clients(array $rows): void
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$mac = strtolower((string)($row['mac'] ?? ''));
|
||||
if (!wifi_valid_mac($mac) || (string)($row['presence'] ?? '') !== 'fdb') {
|
||||
$ip = (string)($row['ip'] ?? '');
|
||||
if (!wifi_valid_mac($mac)
|
||||
|| (string)($row['presence'] ?? '') !== 'fdb'
|
||||
|| filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stmt->execute([
|
||||
':mac' => $mac,
|
||||
':iface' => (string)($row['iface'] ?? 'eth1'),
|
||||
':last_ip' => ($row['ip'] ?? 'N/A') === 'N/A' ? null : (string)$row['ip'],
|
||||
':last_ip' => $ip,
|
||||
':hostname' => ($row['hostname'] ?? 'N/A') === 'N/A' ? null : (string)$row['hostname'],
|
||||
]);
|
||||
}
|
||||
@@ -3434,6 +3466,7 @@ function lan_wol_candidate_macs(array $leases, string $iface = 'eth1'): array
|
||||
SELECT mac
|
||||
FROM lan_wol_clients
|
||||
WHERE iface = :iface
|
||||
AND last_ip IS NOT NULL
|
||||
ORDER BY last_seen_at DESC
|
||||
");
|
||||
$stmt->execute([':iface' => $iface]);
|
||||
@@ -3441,15 +3474,16 @@ function lan_wol_candidate_macs(array $leases, string $iface = 'eth1'): array
|
||||
return [];
|
||||
}
|
||||
|
||||
$macs = [];
|
||||
foreach ($stmt->fetchAll() as $row) {
|
||||
$mac = strtolower((string)($row['mac'] ?? ''));
|
||||
if (wifi_valid_mac($mac) && isset($leases[$mac])) {
|
||||
$macs[$mac] = true;
|
||||
// eth1 is a dedicated direct-connect PC port. Only its most recently
|
||||
// observed lease-backed identity should remain as the offline WOL row.
|
||||
return [$mac];
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($macs);
|
||||
return [];
|
||||
}
|
||||
|
||||
function lan_client_rows(array $leases, array $aliases, array $wifiMacs = [], string $iface = 'eth1'): array
|
||||
|
||||
@@ -207,10 +207,13 @@
|
||||
logStatusLoading: 'Log status loading...',
|
||||
logPersistentJournal: 'Persistent Journal',
|
||||
logCrashLogs: 'Crash Logs',
|
||||
logBootCapture: 'Boot Diagnostics',
|
||||
logOk: 'OK',
|
||||
logWarn: 'Check',
|
||||
logUsage: 'Usage',
|
||||
logBoots: 'Boots',
|
||||
logEvents: 'Events',
|
||||
logLatest: 'Latest',
|
||||
logFilterAll: 'All',
|
||||
logFilterImportant: 'Important',
|
||||
logFilterError: 'Error',
|
||||
@@ -431,10 +434,13 @@
|
||||
logStatusLoading: '로그 보존 상태 확인 중...',
|
||||
logPersistentJournal: '영구 저널',
|
||||
logCrashLogs: '커널 크래시',
|
||||
logBootCapture: '부팅 원인 기록',
|
||||
logOk: '정상',
|
||||
logWarn: '확인',
|
||||
logUsage: '사용량',
|
||||
logBoots: '부팅 이력',
|
||||
logEvents: '기록',
|
||||
logLatest: '최근 판정',
|
||||
logFilterAll: '전체',
|
||||
logFilterImportant: '중요',
|
||||
logFilterError: '오류',
|
||||
@@ -2096,6 +2102,8 @@
|
||||
|
||||
const journal = data.journal || {};
|
||||
const pstore = data.pstore || {};
|
||||
const bootCapture = data.boot_capture || {};
|
||||
const latestBoot = bootCapture.latest || {};
|
||||
const rows = [
|
||||
{
|
||||
title: t('logPersistentJournal'),
|
||||
@@ -2117,6 +2125,17 @@
|
||||
]),
|
||||
state: logStatusState(Boolean(pstore.ok), true),
|
||||
},
|
||||
{
|
||||
title: t('logBootCapture'),
|
||||
desc: bootCapture.path || '-',
|
||||
meta: logStatusMeta([
|
||||
{ label: 'recorder', value: bootCapture.active || '-' },
|
||||
{ label: t('logEvents'), value: Number(bootCapture.count || 0).toLocaleString() },
|
||||
{ label: t('logLatest'), value: latestBoot.classification || '-' },
|
||||
{ label: t('logBoots'), value: latestBoot.booted_at || '-' },
|
||||
]),
|
||||
state: logStatusState(Boolean(bootCapture.ok), true),
|
||||
},
|
||||
];
|
||||
|
||||
els.logStatusList.innerHTML = rows.map(row => `
|
||||
|
||||
Reference in new issue
Block a user