"""Read-only Linux collector, executed via SSH stdin; never imports router code.""" import csv import json import time import subprocess from pathlib import Path def read(path): try: return Path(path).read_text().strip() except OSError: return '' def number(value): try: return float(value) except (ValueError, TypeError): return None def ticks(): values = list(map(int, read('/proc/stat').splitlines()[0].split()[1:9])) return sum(values), sum(values[3:5]) def collect(): errors = [] cpu = {'name': None, 'percent': None, 'temperature_c': None} try: a, ai = ticks() time.sleep(.25) b, bi = ticks() cpu['percent'] = round(100 * (1 - (bi-ai)/(b-a)), 1) if b > a else None except (ValueError, IndexError): errors.append('CPU-Auslastung nicht verfügbar') for line in read('/proc/cpuinfo').splitlines(): if line.startswith('model name'): cpu['name'] = line.split(':', 1)[1].strip() break for path in Path('/sys/class/hwmon').glob('hwmon*'): if read(path / 'name') in ('k10temp', 'coretemp'): value = number(read(path / 'temp1_input')) cpu['temperature_c'] = value / 1000 if value is not None else None break mem = {} for line in read('/proc/meminfo').splitlines(): parts = line.split() if parts[0] in ('MemTotal:', 'MemAvailable:'): mem[parts[0][:-1]] = int(parts[1]) * 1024 total, available = mem.get('MemTotal'), mem.get('MemAvailable') ram = {'total_bytes': total, 'used_bytes': total-available if total is not None and available is not None else None} gpus = [] try: result = subprocess.run(['nvidia-smi', '--query-gpu=index,name,uuid,memory.total,memory.used,utilization.gpu,temperature.gpu', '--format=csv,noheader,nounits'], capture_output=True, text=True, timeout=4, check=True) for row in csv.reader(result.stdout.splitlines(), skipinitialspace=True): index, name, uuid, total, used, usage, temp = row gpus.append(dict(index=int(index), name=name, uuid=uuid, total_mib=number(total), used_mib=number(used), percent=number(usage), temperature_c=number(temp))) except (OSError, subprocess.SubprocessError, ValueError): errors.append('GPU-Messwerte nicht verfügbar') return dict(source='Debian-Server · /proc + hwmon + nvidia-smi', sampled_at=time.time(), cpu=cpu, ram=ram, gpus=gpus, errors=errors) if __name__ == '__main__': print(json.dumps(collect()))