Current deployed version (roko-backup.py) after refactoring from bash to Python. Generated via OpenCode (kimi-k2.7-code). Includes: - rclone streaming progress (log every 5% or 30s) - RotatingFileHandler (max 1MB, 5 backups) - LockFile for concurrent run prevention - Yandex Cloud upload with NO_PROXY bypass - Also includes comparison versions from mimo-v2.5-pro and kimi-k2.7-code
4.7 KiB
4.7 KiB
Refactoring №2: roko-backup.py — улучшенная версия
Исходный код
/home/openclaw/.openclaw/scripts/roko-backup.py (текущая версия — 8 классов, 380 строк)
✅ Сохранить
- Архитектуру (конвейер: Config → LockFile → Collector → Archiver → Uploader → Verifier → Cleaner → Reporter → BackupPipeline)
- Python 3.10+, только stdlib + rclone subprocess
- argparse (--config, --dry-run, --verbose)
- LockFile (защита от параллельных запусков)
- NO_PROXY для Yandex Cloud в subprocess env
- Exponential backoff (10s, 30s, 60s) на retry
🆕 Новый функционал
1. Streaming rclone progress
- Сейчас:
subprocess.run(capture_output=True)— ждём завершения, потом показываем вывод - Надо:
subprocess.Popenс построчным чтением stderr в реальном времени - rclone с
--progressпишет progress строки в stderr - Формат вывода в логах:
2026-07-07 10:30:15 INFO Upload: 15% (95 MiB / 622 MiB) @ 2.1 MiB/s - Парсить
Transferred: ... MiB / ... MiB, ...%из rclone stderr - Не flood-ить лог — логировать прогресс раз в 30 секунд или при каждом новом проценте (кратном 5%)
- По завершении показать финальную статистику (скорость, время)
2. Ротация логов
- Лог-файл:
/home/openclaw/backups/roko-backup.log(НА ДИСКЕ, не в /tmp!) - Максимальный размер: 1 МБ (после этого ротация)
- Хранить: 5 последних ротированных логов (
roko-backup.log.1,.2, ....5) - Использовать
logging.handlers.RotatingFileHandlerиз stdlib - При
--verbose— дублировать в stdout тоже (для отладки вручную)
3. Улучшения кода
- Type hints полные, включая
collections.abc.Generator,ContextManager - Меньше повторений — RCLONE_ENV дублируется в Uploader/Verifier/Cleaner, вынести в конфиг или хелпер
- Документация — docstrings по PEP 257 на английском (краткие, по делу)
- Error handling — отдельный класс BackupError(Exception) вместо голых return 3
- Cleanup гарантированный — даже при падении архиватор должен подчищать staging
Структура (сохраняем конвейер, улучшаем детали)
class BackupError(Exception): ...
class LockError(BackupError): ...
@dataclass(frozen=True)
class Config:
# добавляем log_file: Path, max_log_size: int, max_log_backups: int
...
class LockFile(ContextManager): # добавить __enter__/__exit__
...
class Collector:
EXCLUDE_PATTERNS = (...) # можно сделать конфигурируемым в Config
...
class Archiver:
# архивирует через tarfile (не subprocess tar)
...
class Uploader:
# subprocess.Popen + streaming stderr для progress
UPLOAD_PROGRESS_INTERVAL = 30 # секунд между логами прогресса
PROGRESS_PERCENT_STEP = 5 # логировать каждые N процентов
...
class Verifier: ...
class Cleaner: ...
class Reporter: ...
class BackupPipeline: ...
def setup_logging(verbose, log_file, max_size, max_backups): ...
def main(): ...
Требования к качеству
python3 -c "import ast; ast.parse(open('roko-backup.py').read())"— OK--dry-run --verbose— работает, показывает все источники- Без аргументов — полный цикл без ошибок
--config X— работаетpython3 -c "from roko_backup import Config, BackupPipeline"— импортируемый модуль
Файлы
- Пишем:
/home/openclaw/.openclaw/scripts/roko-backup.py(перезаписать) - Сохраняем:
roko-backup.py.bak(текущая версия) - README: обновить
/home/openclaw/.openclaw/scripts/README.md(добавить про логи и streaming)
Модели для OpenCode
- Основная: mimo-v2.5-pro (OpenCode Go)
- Сравнение: kimi-k2.7-code (OpenCode Go)
- Запасные при зависании (до 3 попыток): minimax-m3 (OpenCode Go), deepseek-v4-pro (OpenCode Go)