← Заметки

inotify-rsync: раскладываем файлы по роутерам, как только они изменились

· openwrt, ucode, rsync, prometheus

Часть файлов на моих хабах появляется в одном месте: один хаб генерирует несколько статических файлов и скачивает несколько больших, а остальные хабы раздают копии. Копии должны догонять быстро. Задача в cron — это либо задержка, либо куча бесполезных запусков, поэтому хотелось, чтобы rsync срабатывал, когда что-то действительно поменялось.

inotify-rsync делает ровно это и ничего больше: следит за каталогами и при изменениях запускает rsync в нужное место.

Настройка

Одна секция UCI на каждое наблюдение:

# /etc/config/inotify-rsync
config watch 'site'
	option enabled '1'
	list src '/data/site'
	option dest 'root@peer.example.org:/data/'
	option rsync_args "-Ppra --delete --delete-delay -e 'dbclient -i /root/.ssh/id_ed25519 -y'"
	list filter 'exclude *.tmp'
	option textfile_dir '/run/prometheus/textfile'

Каждое наблюдение — отдельный инстанс procd, который перезапускается при падении. /etc/init.d/inotify-rsync rsync [watch] запускает синхронизацию вручную — удобно сразу после деплоя. В OpenWrt ssh-клиентом обычно служит dbclient из Dropbear, поэтому rsync_args разбирается с учётом кавычек — -e '…' выше остаётся одним аргументом.

От inotifyd к ucode

Первая версия была shell-скриптом вокруг апплета inotifyd из BusyBox. Она работала, но inotifyd запускается дочерним процессом, и когда procd убивал скрипт при перезапуске, дочерний процесс оставался — осиротевшие наблюдатели копились.

Поэтому в августе 2026 года скрипт переписан на ucode, а для него я написал небольшой модуль на C, ucode-mod-inotify, который даёт ucode прямой доступ к Linux inotify API. Теперь скрипт:

Метрики

Если задан textfile_dir, каждое наблюдение пишет небольшой .prom-файл для textfile-коллектора node exporter:

Счётчики читаются обратно при старте, так что переживают перезапуски, а файл заменяется атомарно. Чтобы за ним следить, хватит двух алертов: растут ошибки, и последний запуск был подозрительно давно.