#!/usr/bin/env python3 """presion-memoria.py — generador de presión de memoria ACOTADO y con seguro. No apunta a un tamaño de hog sino a un SETPOINT de MemAvailable: crece hasta dejar la máquina con los MiB pedidos disponibles y ahí se queda, corrigiendo si el resto del sistema se mueve. La variable controlada es la que importa (memoria disponible), no la que es fácil de fijar. TRES SEGUROS, porque esta máquina es compartida con la granja y con otros agentes: 1. oom_score_adj = 1000 ⇒ si el kernel tiene que matar a alguien, el PRIMERO soy yo, nunca un build de 4 h ni el trabajo de otro agente. Subirlo no necesita privilegios; bajarlo sí. 2. suelo duro: no crece por debajo de PISO_MIB de disponible, pase lo que pase. 3. reloj: se muere solo a los SEGUNDOS, aunque quien lo lanzó desaparezca. ⚠ El relleno es ALEATORIO A PROPÓSITO. El swap de esta máquina es zram (comprimido EN RAM): un hog de ceros se comprime a nada y no genera ni un byte de presión real — mediría cero creyendo medir mucho. Un bloque aleatorio de 4 KiB repetido es incompresible página a página. """ import os, sys, time, signal SETPOINT = int(sys.argv[1]) if len(sys.argv) > 1 else 800 # MiB disponibles objetivo SEGUNDOS = int(sys.argv[2]) if len(sys.argv) > 2 else 600 PISO_MIB = 350 TROZO = 64 * 1024 * 1024 def disponible_mib(): with open('/proc/meminfo') as f: for l in f: if l.startswith('MemAvailable:'): return int(l.split()[1]) // 1024 return 0 try: with open('/proc/self/oom_score_adj', 'w') as f: f.write('1000') # seguro 1: víctima designada except OSError as e: print(f"presion: NO pude marcarme como víctima del OOM ({e}) — abortando por seguridad") sys.exit(1) signal.alarm(SEGUNDOS) # seguro 3: reloj de pared bloque = os.urandom(4096) * (TROZO // 4096) # incompresible para zram lastre = [] print(f"presion: objetivo {SETPOINT} MiB disponibles, piso {PISO_MIB}, {SEGUNDOS}s, " f"disponible ahora {disponible_mib()}", flush=True) try: while True: d = disponible_mib() if d > SETPOINT and d > PISO_MIB: # seguro 2: suelo duro lastre.append(bytearray(bloque)) # bytearray: memoria propia, tocada de verdad elif d < SETPOINT - 128 and lastre: lastre.pop() # el sistema pidió; le devuelvo else: time.sleep(0.25) if len(lastre) % 8 == 0: print(f"presion: lastre={len(lastre)*64} MiB disponible={d}", flush=True) except (MemoryError, KeyboardInterrupt): pass