Открываю рубрику "костылестроение".
Поступила очередная всратая задача (не спрашивайте где я их беру, приносят). Есть некий сервер с
Nextcloud-ом. Некий другой сервер хочет складывать на него файлы по SFTP. Причем да, именно по SFTP и именно в качестве клиента. Нужно эти закачанные файлы переложить в правильную папку на Nextcloud-е и сделать так, чтобы они начали в нём отображаться. Для этого требуется запустить "occ files:scan".
Какие есть сложности. Во-первых, не хочется использовать "обычный" cron, а перекладывать файлы по факту их загрузки. Во-вторых, хочется сканировать Nextcloud-ом как можно меньше, ибо операция ресурсозатратная. В-третьих, хочется как-то сортировать поступающие файлы. Например, по месяцам.
Касемо первого пункта, в линуксе есть механизм "inotify", когда можно подписаться на происходящие в какой-то точке файлововой системы события. Для этого есть userspace-инструменты "inotifywait" и "inotifywatch". Но они предполагают "одноразовое" использование и "демонизировать" их не особо удобно. Поэтому есть более подходящие для этого демоны: incrond и lsyncd. Оба довольно древние, разработка не ведется уже много лет, но тем не менее вполне рабочие. У них плюс-минус похожий функционал, так что можно брать любой. Лично мне чисто исторически привычнее lsyncd.
Конфиг для lsyncd достаточно примитивный. Слушать события "on-create" в той папке, куда падают файлы с SFTP-сервера, и запускать на этом основании нужный мне bash-скрипт.
bash = {
maxProcesses = 5,
onCreate = "/etc/scripts/move"
}
sync {
bash,
source = "/home/uploads"
}
А дальше внутри bash-скрипта начинается собственно костылестроение.
#!/bin/bash
SOURCE="/home/uploads"
DEST="/var/www/data/reports/files/uploads/" # With trailing slash
myself=`/usr/bin/realpath $0`
exec 6< "$myself"
/usr/bin/flock -n 6 || exit 0
sleep 30
umask 007
MONTH=`/usr/bin/date +%Y-%m`
DIR="$DEST$MONTH"
[ -d "$DEST" ] || /usr/bin/sudo -u www-data mkdir "$DEST"
[ -d "$DIR" ] || /usr/bin/sudo -u www-data mkdir "$DIR"
/usr/bin/find "$SOURCE" -maxdepth 1 -type f -name '*.csv' -exec mv --backup=t -t "$DIR" {} +
/usr/bin/chown -R www-data:www-data "$DIR"
/usr/bin/find "$SOURCE" -type f -not -path "$SOURCE/.ssh/*" -delete
/usr/bin/sudo -u www-data /usr/bin/php /var/www/nextcloud/occ files:scan --quiet --path "/reports/files/uploads/$MONTH"
exit 0
Открываем на чтение самого себя и пробуем установить блокировку. Если не получилось, выходим. Это нужно чтобы исполнялась только одна копия скрипта. Спим 30 секунд на случай, если клиент захочет положить несколько файлов. Как всё загрузит, так и начнём шевелиться, а пока отдыхаем. Проверяем-создаем директории куда собираемся раскладывать загруженное. Перемещаем интересующее, удаляем всё остальное (кроме ssh-ключей, ага). И последним этапом запускаем сканирование NextCloud-ом прицельно по одной папке, куда только что переместили выгрузки.
Да, подход не идеален, но в качестве костыля на несколько десятков файлов в день вполне годится.
Как всегда, критика приветствуется.