#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ ОСВОБОДИТЬ ДИСК — сжатием, а не удалением. Почему не удаляем 4.5 ГБ «дублей»: сверка показала, что СДЕЛКИ по этим ботам действительно есть в базе (trades_*). Но внутри каталогов лежат ещё и СИГНАЛЫ (поля ts/symbol/signal/tf/dir/strength/regime/price) — а таблица сделок их не содержит. То есть «дубль» верен только наполовину. gzip даёт на текстовом jsonl примерно десятикратное сжатие. Место освобождается почти как при удалении, но не теряется ничего и всё обратимо `gunzip`. Удаляем только то, что мусор без оговорок: аварийные дампы и старый журнал. python3 disk_reclaim.py сухой прогон python3 disk_reclaim.py --apply выполнить """ import os, subprocess, sys, time APPLY = "--apply" in sys.argv RUNS = "/opt/arena/runs" def sh(c, t=1800): try: r = subprocess.run(c, shell=True, capture_output=True, text=True, timeout=t) return (r.stdout or r.stderr or "").strip() except Exception as e: return f"<{type(e).__name__}>" def gb(kb): return f"{int(kb)/1048576:.2f} ГБ" if str(kb).isdigit() else "?" print("диск до:", sh("df -h / | awk 'NR==2{print $3\" / \"$2\" (\"$5\")\"}'")) # ── 1. сжатие jsonl/json старше 30 дней ── n = sh(f"find {RUNS} -type f \\( -name '*.jsonl' -o -name '*.json' \\) -mtime +30 ! -name '*.gz' | wc -l") sz = sh(f"find {RUNS} -type f \\( -name '*.jsonl' -o -name '*.json' \\) -mtime +30 ! -name '*.gz' " f"-exec du -cxsk {{}} + 2>/dev/null | tail -1 | cut -f1") print(f"\n1. сжать: {n} файлов, {gb(sz)}") print(f" ожидаемо освободится ~{int(sz)/1048576*0.9:.1f} ГБ (gzip на jsonl даёт ~10x)") if APPLY: print(" жму (может занять несколько минут)…") out = sh(f"find {RUNS} -type f \\( -name '*.jsonl' -o -name '*.json' \\) -mtime +30 " f"! -name '*.gz' -print0 | xargs -0 -P 4 -n 50 gzip -6 2>&1 | tail -3", t=3000) print(" " + (out or "готово")) # ── 2. аварийные дампы ── n = sh("find / -xdev \\( -name 'core.*' -o -name '*.core' \\) 2>/dev/null | wc -l") print(f"\n2. аварийные дампы: {n} шт") if APPLY and n.isdigit() and int(n) > 0: sh("find / -xdev \\( -name 'core.*' -o -name '*.core' \\) -delete 2>/dev/null") print(" удалены") # ── 3. журнал systemd ── print(f"\n3. журнал systemd: {sh('journalctl --disk-usage')}") if APPLY: print(" " + sh("journalctl --vacuum-time=14d 2>&1 | tail -1")) # ── 4. кэш apt ── print(f"\n4. кэш пакетов: {sh('du -xsh /var/cache/apt 2>/dev/null | cut -f1')}") if APPLY: sh("apt-get clean 2>/dev/null") print(" очищен") print("\nдиск после:", sh("df -h / | awk 'NR==2{print $3\" / \"$2\" (\"$5\")\"}'")) if not APPLY: print("\nсухой прогон. Для выполнения добавьте --apply")