Никак не мог найти себе подходящую программу для автоматической синхронизации файлов с сервером при их изменении, пришлось написать свою на bash. Вот ее активная часть:
while true; do
if [[ -n $(git status -s) ]]; then
cd $1
git add .
git commit -m "Git commit `date +'%d.%m.%Y %H:%M:%S'`"
git push origin master
notify-send -i face-smile "Синхронизация выполнена"
fi
done
Т.е программа постоянно смотрит вывод git status и если обнаружит, что файл изменен, она автоматически его коммитит. Работает идеально. Но я беспокоюсь за чистоту программирования и еще за сохранность моего жесткого диска. Она ведь постоянно долбится в этот git status, насколько это правильно? Можно было конечно не делать бесконечным циклом, а запускать по cron, но мне нужна именно моментальная синхронизация. С другой стороны, как устроены другие популярные программы для синхронизации или мониторинга чего-либо, типа Dropbox или Seafile? Я не разбирался, что у них происходит под капотом, может они тоже также долбятся в свое?
Расскажите пожалуйста об этом, если знаете, и может быть дадите какие-нибудь советы, как улучшить этот алгоритм?
Пробовал inotifywait. Она к сожалению не умеет задать для мониторинга файлы определенных расширений. Вообще нельзя задать файлы по маске. Можно разве что сделать exclude других файлов, да и то это сделано через одно место.
И как ты потом найдешь среди коммитов нужный и поймешь причину правок? По diff'у?
Вообще тебе нужно постоянно синхронизировать? Может какой-нибудь sleep стоит прикрутить? Или посмотреть в сторону того, чему ты изменяешь файлы - если это какой-нибудь vim\emacs то там можно (скорее всего, не пробовал) прикрутить чтоб коммит выполнялся при сохранении файла.
У Dropbox вроде fuse использовался, сейчас пропихивают что-то там в ядро в виде модуля (не в курсе приняли ли это или нет).
Она к сожалению не умеет задать для мониторинга файлы определенных расширений.
А зачем? В твоем случае пусть хоть что-то изменится в нужном тебе каталоге, а там ты уже будешь делать всякие $(git status -s). Всё же легче, чем постоянно поллить.
А бесконечный цикл - это очень плохо. Хоть sleep 3 сделай.
Гит долбится не в «свое», а в каждый stat/mtime как минимум, как максимум в diff с оригиналом из .git. Поскольку при таком поллинге метаданные и так в кеше, грузишь ты только проц. Поставь адекватный таймаут, например 1 — имхо достаточно моментально, учитывая время самого пуша.
В твоем решении кстати в гит могут залетать частичные сейвы и сейвы-ин-прогресс, не знаю плохо это или нет.
-if [[ -n $(git status -s) ]]; then
+if [ -n $(git status -s) ]; then
Работает идеально
Оно racy, ты ещё не наступил или не заметил. Оно добавит в репозиторий временные файлы редактора и недозаписанные файлы в процессе записи.
и еще за сохранность моего жесткого диска
От чтения ещё никто не умирал, тем более оно всё всё равно в кэше. Вот то что эта помойка на 100% грузит одно ядро - это не дело. Хотя бы sleep 1 добавил.
С другой стороны, как устроены другие популярные программы
В системе есть API для слежения за изменениями файловой системы: ЕМНИП, inotify в linux и kqueue во FreeBSD. Есть библиотеки которые от этого API абстрагируются, gamin например. Во FreeBSD есть ещё libinotify, которая видимо просто предоставляет совместимое с linux API. Что-то из этого и используют.
Дело в том, что при открытии тех файлов, которые я редактирую, в той директории создается несколько временных файлов, которые присутствуют, пока редактор открыт и удаляются, когда он закрывается. Но exclude в этом inotifywait реализован через такое одно место, что мне выпилить ложные срабатывания так и не удалось. Указать файлы определенных расширений для слежки inotifywait тоже не позволяет. Вот и пришлось изобретать собственный велосипед.
Но exclude в этом inotifywait реализован через такое одно место, что мне выпилить ложные срабатывания так и не удалось.
Так может наоборот передать ему полный список файлов, за которыми надо следить? Вроде такого (лучше директории, конечно, передавать, ну и событие нужное указать):
Ничего себе, а как же plumbing там, всё такое, как же каркас для построения системы контроля версий под задачу, как же низкоуровневая версионированная файловая система на объедках Git, как же вековая мудрость вождя нашего?
Я их и сунул. А для чего мне троекратное срабатывание кода во время редактирования файла и естественно троекратное уведомление, что файл синхронизирован?
Какая разница, как этот статус отслеживать? Можно было бы и в if, но в любом случае эту конструкцию надо обернуть в бесконечный цикл, потому что в противном случае скрипт благополучно завершится и все.
«git status -s» ничего не возвращает в случае если нечего коммитить, т.е null
Дело в том, что при открытии тех файлов, которые я редактирую, в той директории создается несколько временных файлов, которые присутствуют, пока редактор открыт и удаляются, когда он закрывается.
Всё равно вызовов будет меньше, чем, даже при sleep 2. Ну, решать тебе.
Не использовать bash-специфичный синтаксис чтобы скрипт сломался на других шеллах? Странное у вас «чтобы жизнь мёдом не казалась». Но да, кавычки конечно нужно добавить.
Ага. И еще хорошо на Си++ не писать, чтоб программа не дай бог не «сломалась», когда вы ее компилятором Си будете собирать.
Странное у вас «чтобы жизнь мёдом не казалась». Но да, кавычки конечно нужно добавить.
И однако забыли. А потом и еще про что-нибудь нужно будет не забыть, а потом еще про что-нибудь. Даешь любые лишения, лишь бы современными средствами не пользоваться!