Автозагрузка из DropboxOwncloud
Опубликовано 26 November 2015 в misc
Upd 17/03/2016: скрипты немного исправлены для работы с Owncloud
Зачем это всё?
Как я уже говорил, сайт работает на Pelican. А узнал я о нём от замечательного, но, к сожалению, умирающего сервиса calepin.co. Этот сервис предлагает очень удобную штуку- подключается к Dropbox аккаунту и из файлов, размещённых в его папке, создаёт статический сайт на своём сервере. Можно даже своё доменное имя прикрутить, а можно и их воспользоваться. В общем всё было бы хорошо, если бы не нереальный долгий отклик их сервера из России- пользоваться невозможно. Там то я узнал о том, что работает он на Pelican.
В общем, с тех пор я продолжал хотеть такую же штуку- автоматическая сборка и загрузка сайта при изменении файлов в определённой подпапке в Dropbox. Удобно же писать в бложик, когда бьёшь баклуши появилась свободная минутка на работе, а потом вжжжик и всё на сайте уже. Плюс, на Dropbox есть версионность файлов, то есть можно откатиться в случае ахтунга.
И так, берём в одну руку Bash, в другую Linux и приступаем к упражнениям!
Incron- наш лучший друг!
Incron- это такая служба, которая следит за изменениями в файловой системе, и если, в указанном месте происходит указанное событие- выполняет заданную команду. Вот, собственно, и план:
- пишем скрипт по сборке сайте и его копировании на сервер;
- добавляем приятную удобность;
- настраиваем incron;
- Готово!
Скрипты
Принцип работы скрипта следующий: Incron следит за папкой, в которой хранятся исходные файлы Pelican. Там же создан файл upload.txt
, изменением которого и происходит активация сборки и копирования сайта. Так сделано для того, чтобы скрипт не выполнялся при каждом сохранении файла внутри наблюдаемой папки. Пэтому в incron
скрипту в виде параметра $#
передаётся имя измененного файла (точнее файла, у которого изменились атрибуты), скрипт анализирует полученное и запускает или нет процедуры сборки и копирования сайта.
Почему нельзя просто следить за файлом? Потому что оказалось, что при обычном изменении файла происходит его фактическое удаление и пересоздание. Таким образом, изменяется node (не знаю как по-русски), и incron
и inotify
теряют возможность следить за ним.
Скрипт выглядит следующим образом:
#!/bin/bash
export LANG=ru_RU.UTF-8
par=${1%.*}
if [ -n "$par" ] && [ $par == "cid" ]; then
/home/USERNAME/.gem/ruby/2.3.0/bin/sass /home/USERNAME/.config/pelican/themes/Pelican-Cid/src/sass/cid.sass /home/USERNAME/.config/pelican/themes/Pelican-Cid/static/css/cid.css 2>&1
elif [ -n "$par" ] && [ $par == "upload" ]; then
pelican -s /home/USERNAME/.config/pelican/pelicanconf.py /home/server/http/owncloud/data/OCUsername/files/Personal/Blog/ -o /tmp/output
rsync -avc --delete /tmp/output/ hostingUserName@hosting address:/home/public
rm -rf /tmp/output
elif [ -n "$par" ] && [ $par == "test" ]; then
pelican -s /home/USERNAME/.config/pelican/pelicanconf.py /home/server/http/owncloud/data/OCUsername/files/Personal/Blog/ -o /tmp/output
fi
Про cid
и sass
: это сделано для того, чтобы следить за изменением исходных файлов CSS и, соответсвенно, пересобирать их при изменении.
Так как на моём сайте всё картинки- черно белые, решено было это тоже автоматизировать. При появлении картинки в папке images
автомаГически, при помощи imagemagick
мы меняем ей права (иногда при скачивании из Интернета они не правильные), делаем её ЧБ и меняем размер до 700px по ширине (если необходимо). Для того, чтобы скрипт поменял размер картинки, её нужно сохранить в виде resize_имя_файла
, скрипт потом сам удалит лишнее. Вот так он выглядит:
#!/bin/bash
chmod 644 $1\/$2
convert $1\/$2 -colorspace Gray $1\/$2
if [[ ${2:0:7} == resize_ ]];
then
convert $1\/$2 -resize 700x700 $1\/${2#*_}
rm -f $1\/$2
php -f /usr/share/webapps/owncloud/occ files:scan --path OCUserName\/files\/Personal\/Blog\/images > /dev/null 2>&1
fi
Установка и настройка incron
Не знаю как в вашем, а в моём дистрибутиве incron
есть в стандартных репозиториях, так что устанавливаем:
sudo pacman -S incron
Принцип работы- такой же как и в обычном cron
- конфигурация через incrontab
:
$ incrontab -e
Синтаксис следующий:
/путь/который/нужно/мониторить СОБЫТИЕ /какую/команду/выполнять $передаваемыеПараметры
Здесь всё расписано на буржуйском.
Получилось вот что (запускается от пользователя USERNAME):
/home/server/http/owncloud/data/OCUsername/files/Personal/Blog IN_ATTRIB /home/USERNAME/bin/build-publish.sh $#
/home/USERNAME/.config/pelican/themes/Pelican-Cid/src/sass IN_ATTRIB,IN_MOVED_TO /home/USERNAME/bin/build-publish.sh $#
А это запускается от пользователя apache (http)
sudo -u http incrontab -e
/home/server/http/owncloud/data/Speranskiy/files/Personal/Blog/images IN_CREATE,IN_MOVED_TO /home/speranza/bin/prepImage.sh $@ $#
Почему IN_ATTRIB
? Да потому что incron
далеко не образец написания программ и он не определяет сколько изменений произошло на самом деле. Он работает очень просто- произошло событие- выполнил команду. А проблема в том, что при простом изменении файла, например, IN_MODIFY
вообще не происходит, а IN_CLOSE_WRITE
происходит 2 раза и скрипт выполняется два раза. Вообще интересно наблюдать как происходят события файловой системы при помощи inotifywait
, что предоставляется пакетом inotify-tools
:
$ inotifywait --monitor /путь/который/нужно/мониторить
В общем при изменении файла гарантированно один раз происходит только изменение атрибутов, поэтому это событие и использовано.
Так же, помните, что в incron
не предусмотрена защита от "зацикливания", поэтому если действие, приводящее к изменению файла вызывается атрибутом IN_MODIFY
, то это приведёт к повисанию всей системы- OS будет занята перезаписыванием одного и того же файла бесконечно.
Пуск и отладка!
Сервис ставится в автозагрузку и запускается следующим образом (для systemd
):
sudo systemctl enable incrond
sudo systemctl start incrond
Да, сервис работает от root, но правила выполняет от пользователя.
Посмотреть что делает сервис можно так:
journalctl -f -u incrond
Но в journalctl
пишутся только выполняемые команды и подробностей там не видно. Чтобы посмотреть глубже можно остановить службу и запустить её прямо из терминала c параметром -n
:
sudo systemctl stop incrond
sudo incrond -n
Вывод
В результате получилось не совсем то, что хотел- для работы нужно держать ноутбук включенным. Конечно я не буду этого делать и пускай обновляется когда я или моя ненаглядная его включит. По хорошему, нужно было на сервере устанавливать dropbox-cli
и всё это дело настраивать там, но мой хостинг почему-то работает на FreeBSD, а я с ней не дружу. Из плюсов моей реализации- ограничение траффика на хостинг, а он у меня платный, так что- экономия.