Иногда, чтобы решить свою проблему, приходится написать инструмент. А иногда — чтобы написать инструмент, приходится решить свою проблему. Короче, как обычно, всё началось не с идеи сделать утилиту, а с того, что добавилась пара важных документов (по иппотке) к существующему зоопарку данных, которые надо хранить.
Как я к этому пришел
У меня давно назрела проблема: синхронизировать разные файлы с разных рабочих мест — по крайней мере дома и на работе. Документы (важные), сохранения из игр, книги для читалки. Ну и надёжный архив всего этого добра, потому что терять даже что-то незначительное это боль 🤕.
Просто положить всё в одно облако — хорошо, но нужен ещё постоянный процесс актуализации. Яндекс Диск работает, Google Drive может изменить условия, Dropbox может внезапно ограничить доступ. Поэтому идея была простая: хранить копии везде. Яндекс Диск, Google Drive, Mail.ru Cloud, Dropbox — чем больше, тем надёжнее. Только файлы, только хардкор!
Раньше я обходился консольным демоном yandex-disk — он работал, но только с Яндексом. Потом перешёл на самописные bash-скрипты, которые вызывали rclone напрямую. Это работало… до поры до времени. Конфигурация разрасталась, порядок синхронизации был важен (нельзя синкать из пустого облака в другое до того, как туда прилетели файлы) и всякое подобное. Проблема!
Когда появились нормальные ИИ-ассистенты для кодинга, я решил, что пора пробовать, а мне нужен нормальный инструмент. Declarative configuration, predictable order, automatic error handling и пр. Так родился Syncerman.
Из говна и палок архитектура и технологии
Syncerman написан на Go — выбрал его только за простоту распространения (один бинарник).
В основе лежит rclone bisync — двусторонняя синхронизация с сохранением метаданных. Syncerman не пытается переизобрести колесо синхронизации, а выступает оркестратором над rclone, предоставляя удобный CLI и YAML-конфигурацию. Никаких серверов и БД.
YAML-конфигурация
Вместо папок с ссылками на bash-скрипты — чёткая структура:
jobs:
important:
name: "Важное"
priority: 10
tasks:
- from: "local:/home/jerry/cloud/mirror/Documents"
to:
- path: "gdrive:folders/Documents"
- path: "ydisk:folders/Documents"
- from: local:Наследие
to:
- path: gdrive:Наследие/
args: ["--force"]
- path: ydisk:Наследие/
args: ["--force"]
- path: mailru:Наследие/
args: ["--force"]
games:
name: "игрули"
priority: 20
tasks:
- from: "local:games_sync"
to:
- path: "ydisk:folders/games_sync"
Порядок tasks и to внутри массивов сохраняется строго. Это критично для цепочек: local → Google Drive → Yandex Disk. Без этого — катастрофа.
Проблемасики
rclone bisync требует state-файлы для работы (они лежат где-то в папке пользователя). При первом запуске на новой паре путей он падает с ошибкой "cannot find prior Path1 or Path2 listings". Syncerman детектирует это по двум паттернам в выводе и автоматически перезапускает синхронизацию с флагом --resync. Пользователь даже не замечает проблемы. Раньше делал руками.
На ранних этапах обнаружился критический баг: из-за использования map в Go порядок выполнения целей был недетерминированным. Для линейных цепочек это катастрофа: если сначала синкать из пустого Yandex в Google, а потом из локальной папки в Google — быть беде. Проблема! Так появились массивы.
Результат
Syncerman версии **0.3.6** сейчас работает в production — то есть на моих машинах :) Само собой нужны пруфы, и их есть у меня!
- бинарники для Linux и Windows (сборка сразу подо всё)
- GitLab CI как в лучших домах
- Покрытие тестами - самому было бы лень писать а тут юнит-тесты для всех ключевых пакетов (config, rclone, sync), интеграционные тесты (не просто интеграционные а целые bash-сценарии с десятком шагов ).
Публичные репозитории (это мой фетиш):
- Gitlab https://gitlab.com/kinnalru/syncerman
- Github https://github.com/kinnalru/syncerman
- Gitflic https://gitflic.ru/project/kinnalru/syncerman
- Gitverse https://gitverse.ru/kinnalru/syncerman
Использование
Мой crontab выглядит так:
# Синхронизация документов и сохранений 2 рааз в час и лог для ручной проверки
10,30 * * * * /bin/sh -lc "cd /home/jerry/cloud/mirror && syncerman sync 2>&1 | tee ./lastrun.log"
Конфигурация зеркалирует локальные папки во все облака (настроенные в rclone) одновременно, а затем синхронизирует облака между собой. Если одно облако отвалится — данные остаются в остальных. Если rclone выдаст first-run ошибку — Syncerman сам всё починит.
Вместо вывода
Появление ИИ-ассистентов снизило порог входа для написания таких инструментов. Раньше мне было лень писать то, что и так работает с помощью пары строк на bash. А сейчас это делаю не я :) — разбор выхлопов rclone, обработка edge cases и тестирование делаются очень легко. Я могу заняться решением проблем (архитектурой и требованиями), а рутина "делается сама".
Второй фетиш это ссылочки:
- rclone bisync - это база
- unison - еще одна классная штука по теме синхронизации, она прочно заняла место в моём сердце, но об это в другой раз

Top comments (0)