Как стать автором
Обновить

История создания домашнего облака. Часть 3. Создание персонального облака — установка и настройка Nextcloud

Время на прочтение36 мин
Количество просмотров161K
На пути создания своего облачного сервиса пока мы освоились в системе Debian и создали веб-сервер. Теперь пришла пора для финального шага — создания и настройки персонального облака на базе сервера Nextcloud.





Оглавление


Часть 1. Настройка среды Debian для повседневного использования
Часть 2. Создание сервера — настройка LAMP в Debian
Часть 3. Создание персонального облака — установка и настройка Nextcloud
Часть 4. Актуализация 2018 – Debian 9 и Nextcloud 13
Часть 5. Актуализация 2019 – PHP 7.2, MariaDB 10.4 и Nextcloud 17



Быстрая навигация по главе


Предисловие
Подготовка сервера для установки Nextcloud
Установка Nextcloud
Организация места хранения данных Nextcloud
Настройка доступа к виртуальной машине Nextcloud из локальной сети
Настройка Nextcloud
Дополнительная «тонкая» настройка Nextcloud
Защита для Nextcloud
Синхронизация с облаком смартфонов
Синхронизация с облаком персонального компьютера
Послесловие



Предисловие


Вот мы и подошли к тому самому, ради чего всё затевалось и к чему не быстро продвигались. В этой части будет описана установка и некоторые моменты в настройке сервера Nextcloud в виртуальной машине VMWare, а также небольшой опыт работы с ним в виде синхронизации содержимого пары смартфонов и папок настольного компьютера под управлением Windows. Нижеприведённые инструкции по установке Nextcloud подразумевают, что сервис разворачивается на сервере, который был создан по инструкциям в предыдущей части моего повествования.

Изначально эта глава планировалась небольшой, так как я хотел ограничиться только описанием установки и настройки Nextcloud, по сути закончив эту историю о «простом входе в Linux под конкретную задачу». Но, подумав, что кому-то это может показаться интересным, потом всё же решил показать как я решил вопрос синхронизации папок своего домашнего компьютера, поэтому эта завершающая глава плавно перетекла из чётких инструкций что и как делать в, по сути, программирование. Этим объясняется некоторый «винегрет» в этой части – начинается она с работы и настройки в Linux, перетекая на уровень настроек сети и виртуального софта, а заканчивается строганием костылей в Windows. С другой стороны, этот цикл статей имеет название «История создания…» и я всё же решил рассказать её до конца.

Примечание
При дальнейшем чтении в конструкциях вида http:// 127.0.0.1 (https:// 127.0.0.1) пробел после http:// (https://) необходимо убирать при вводе в адресную строку браузера. Пробел вставлен при публикации этой статьи с целью воспрепятствовать автоматической конвертации движком сайта текста в ссылки.



Подготовка сервера для установки Nextcloud


Nextcloud – это веб-приложение, которое имеет набор файлов и работает с базой данный MySQL. Веб-приложение устанавливается как обычный сайт, для установки которого нужно загрузить файлы «движка» на сервер, запустить установочный файл и при установке указать реквизиты доступа к базе данных, заранее созданной для этого сайта.

Создаём директорию, в которой будут размещены файлы Nextcloud:
# mkdir /var/www/nextcloud

Я решил отказаться от HTTP, оставив доступ только по HTTPS. Для этого нужно настроить apache.

Открываем файл:
# nano /etc/apache2/sites-available/default-ssl.conf
И перед тегом добавляем следующее содержимое:

<Directory /var/www/nextcloud>
  Options FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>


Отключаем конфигурацию HTTP:
# a2dissite 000-default.conf

Закрываем порт 80:
# ufw delete allow 80

И перезапускаем веб-сервер:
# service apache2 restart

Теперь нужно создать базу данных для nextcloud. Входим в mysql, введя пароль от суперпользователя mysql:
# mysql -u root -p

Создаём базу данных с названием nextcloud:
mysql> CREATE DATABASE `nextcloud`;

Создаём пользователя с именем nextcloud и тривиальным паролем nc123:
mysql> CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'nc123';

Выдаём полный доступ пользователю nextcloud на базу nextcloud:
mysql> GRANT ALL PRIVILEGES ON `nextcloud`.* TO 'nextcloud'@'localhost';

Обновляем таблицу привилегий:
mysql> FLUSH PRIVILEGES;

Выходим из mysql:
mysql: mysql> exit

Помимо этого, необходимо установить дополнительные модули для PHP:
# apt-get install curl libcurl3 libcurl3-dev php5-curl
# a2enmod rewrite


В первой части этой истории нами были открыты порты для сетевого и почтового взаимодействия, но под нашу целевую задачу они не требуются и лучше их закрыть. Удаляем правила:
# ufw delete allow 138/udp
# ufw delete allow 139/udp
# ufw delete allow 139/tcp
# ufw delete allow 445/tcp
# ufw delete allow 25
# ufw delete allow 465
# ufw delete allow 110
# ufw delete allow 143
# ufw delete allow 993




Установка Nextcloud


Скачиваем файлы и распаковываем их в предназначенную директорию:
# wget download.nextcloud.com/server/releases/nextcloud-11.0.2.tar.bz2
# tar xjf nextcloud-11.0.2.tar.bz2 -C /var/www


Изменяем права на папку:
# chmod 755 /var/www/nextcloud

И назначаем владельцем этой папки веб-сервер, чтобы не было проблем с записью в неё:
# chown -R www-data:www-data /var/www/nextcloud

Всё! Сервис установлен, если набрать в браузере https:// 127.0.0.1/nextcloud, то откроется мастер установки. Но подождём с этим, предварительно подготовив место для хранения пользовательских данных.

Стоит упомянуть, что версия Nextcloud 11.0.2 на данный момент является довольно устаревшей и содержащей уязвимости, которых нет в более новых и актуальных версиях, поэтому если и устанавливать ветку 11.х, то лучше установить более свежую версию (на начало 2018 года — это версия 11.0.7).



Организация места хранения данных Nextcloud


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

По умолчанию синхронизируемый контент будет храниться в директории /var/www/nextcloud/nxcdata. Меня этот вариант сразу не устраивал по нескольким причинам. С одной стороны, я бы не хотел постоянного увеличения объёма файла виртуального диска. С другой стороны, хотелось бы иметь отдельное и независимое от виртуальной машины решение хранения данных. Самое простое, что сразу приходит в голову – использование USB-диска. В случае нехватки места диск можно просто заменить. В случае необходимости его можно подключить к другому компьютеру и скачать необходимые файлы. Мобильно и удобно. Однако USB 2.0 использовать не хотелось по причине относительно небольшой пропускной способности по современным меркам, а с USB 3.0 у меня ничего не получилось – софт виртуализации (WMVare и VirtualBox) никак не хотел нормально пробрасывать устройства, подключенные через контроллер USB 3.0.

Аппетиты, в процессе работы над созданием облака, у меня возросли и мне уже никак не меньше одного терабайта надо было, поэтому, в конце концов, я решил подключить к виртуальной машине обычный двухтерабайтный жесткий диск, который уже был размещён и подключен внутри компьютера. В случае необходимости он без проблем вытаскивается и подключается через имеющийся переходник SATA <-> USB 3.0.

Итак, основная идея — организовать постоянную точку для подключения директории с пользовательским контентом вне каталога /var/www/nextcloud, в которой создаётся символьная ссылка с названием nxcdata, ссылающаяся на реальный каталог с данными, который может быть подключен различными способами на различных носителях.

Создаём каталог:
# mkdir /mnt/nxcdata

Изменяем права:
# chmod 770 /mnt/nxcdata

Делаем владельцем веб-сервер:
# chown www-data:www-data /mnt/nxcdata

Я могу как угодно и где угодно располагать данные, главное – символьную ссылку на эту директорию размещать в директории /mnt/nxcdata и назвать её nxcdata, т.е. полный путь будет выглядеть как /mnt/nxcdata/nxcdata.

Сначала я протестировал решение для локальной папки, которую создал в домашнем каталоге.

Создал в нужном месте папку:
$ mkdir /home/user/nxcdata

Изменил права:
# chmod 755 /home/user/nxcdata

Сделал владельцем веб-сервер:
# chown -R www-data:www-data /home/user/nxcdata

Создал символьную ссылку:
# ln -s /home/user/nxcdata /mnt/nxcdata/nxcdata

Это решение было работоспособно, поэтому можно двигаться дальше. Внешний каталог для данных можно подключить двумя способами – через сервис VMWare Shared или напрямую как физический диск или раздел. Надо понимать, что первое решение возможно только при наличии установленных vmware tools, которые без проблем ставятся только при наличии графического интерфейса операционной системы (в ином случае придётся править установочные скрипты vmware tools). Если же отказаться от графического интерфейса, то остаётся только вариант подключения диска напрямую к виртуальной машине, но и с этим решением мне пришлось изрядно помучиться. Через некоторое время я всё же нашёл стабильно работающий вариант, с учётом которого был придуман универсальный скрипт, вобравший в себя оба варианта подключения.

Для папки, подключаемой через VMWare Shared Folders в разделе Shared Folders настройках виртуальной машины необходимо подключить необходимую папку из хостовой системы и дать ей название vmw-nxcdata. Эта папка может ссылаться на какую-то директорию на жестком диске или прямо на корневой каталог какого-то диска в хостовой системе.

Подключенная папка появится в виртуальной системе автоматически по пути /mnt/hgfs/vmw-nxcdata. Однако проблема в том, что веб-серверу будет недостаточно прав для записи файлов по этому пути и стандартными средствами системы переназначить права для этой директории не получится. Поэтому мне пришлось разобраться как вручную монтировать подобные ресурсы.

Создаём папку:
# mkdir /mnt/vmw-nxcdata

Выполняем монтирование, используя модуль vmhgfs, который установился вместе с vmware-tools:
# mount -t vmhgfs -o uid=www-data,gid=www-data,fmask=007,dmask=007 .host:/vmw-nxcdata /mnt/vmw-nxcdata

Монтирование нужно выполнять именно с такими параметрами для беспроблемной работы веб-сервера в будущем. Изначально я монтировал без указания uid/gid и масок, но ни к чему хорошему это потом не приводило, так как изменить права после монтирования уже не получалось. После выполнения монтирования может выдаваться: «Could not add entry to mtab, continuing», — однако монтироваться и работать будет.

Отлично, директорию мы примонтировали. Теперь можно разместить символьную ссылку на эту директорию в /mnt/nxcdata. Но не хотелось бы при каждом запуске или перезапуске сервера делать это вручную. Самый простой способ – в файле /etc/rc.local вписать вышеприведённую команду для монтирования до строчки «exit 0». Однако мне хотелось, чтобы при выключении виртуальной машины происходило автоматическое гарантированное размонтирование для надёжной сохранности данных. И я решил сделать всё на уровне сервисов и немного разобраться с механизмами init/update-rc, тем более мне было любопытно и это оказалось довольно интересно.

Смысл нижеследующих действий в том, чтобы создать системный сервис, который бы вызывался и выполнял заранее заданные команды при включении или выключении системы. Сервис описывается скриптом, составленным по определённым правилам и располагается в /etc/init.d. Блок INIT INFO располагается в самом начале скрипта и содержит служебную информацию, в которой хотелось бы отметить директивы Default-Start и Default-Stop – они задают уровни выполнения, на которых скрипт должен быть запущен или остановлен по умолчанию.

Уровни выполнения:

0 – выполнение скрипта при выключении системы
1 – выполнение скрипта при запуске системы в однопользовательском режиме
2 – выполнение скрипта при запуске системы в многопользовательском режиме
3 – 5 – зарезервировано
6 – выполнение скрипта при перезагрузке системы

После написания скрипта он задействуется, используя механизм update-rc, который, фактически, на скрипт создаёт ссылки в нужных каталогах /etc/rc0.d — /etc/rc6.d, содержимое которых соответствует выполняемым задачам по уровням запуска. Ссылки можно создавать и самостоятельно, но, в отличии от включения или отключения конфигураций веб-сервера apache, здесь нужно учитывать много нюансов, поэтому включать или отключать сервис нужно через update-rc.

Итак, создаём файл:
# nano /etc/init.d/nxcdata_automount.sh

И записываем в него следующее содержимое:

#!/bin/sh
# nxcdata_automount.sh 1.0

### BEGIN INIT INFO
# Provides: myscript
# Required-Start:
# Required-Stop:
# Default-Start: 1 2 3 4 5
# Default-Stop: 0 6
# Short-Description: nxcdata_automount.sh 1.0
# Description: nxcdata_automount.sh 1.0
### END INIT INFO

. /lib/lsb/init-functions

# Start actions
perform_start()
{
  log_daemon_msg «Start nxcdata_automount»
  sleep 30
  mount -t vmhgfs -o uid=www-data,gid=www-data,fmask=007,dmask=007 .host:/vmw-nxcdata /mnt/vmw-nxcdata
  #mount -t ntfs-3g -o uid=www-data,gid=www-data,fmask=007,dmask=007 /dev/sdb1 /mnt/sdb1
  #mount -t ext4 /dev/sdb1 /mnt/sdb1
  sleep 5
  service fail2ban restart
  log_end_msg 0
  return 0
}

# Stop actions
perform_stop()
{
  log_daemon_msg «Stop nxcdata_automount»
  umount /mnt/nxcdata
  log_end_msg 0
  return 0
}

case $1 in
  start)
    perform_start
    ;;

  stop)
    perform_stop
    ;;

  *)
    echo “Usage: /etc/init.d/myscript {start|stop}”
    exit 3
    ;;
esac


Обратите внимание на пару закомментированных команд в секции perform_start – это наш задел на будущее. Так же, после выполнения монтирования перезапускается сервис fail2ban.

Парадокс заключается в том, что спустя год я уже не помню почему я так сделал, но сильно сомневаюсь, что это сделано просто так. Очевидно после выполнения монтирования сервис по непонятной причине падал или неудачно запускался изначально и его приходилось перезапускать вручную.

После такого отвлечения продолжаем настройку далее. Создаём символьную ссылку:
# ln -s /mnt/vmw-nxcdata /mnt/nxcdata/nxcdata

Делаем наш скрипт исполняемым:
# chmod +x /etc/init.d/nxcdata_automount.sh

Добавляем скрипт в автозагрузку:
# update-rc.d nxcdata_automount.sh defaults

Перезагружаем систему и убеждаемся, что автомонтирование прошло успешно и по нужным путям всё доступно.

Для удаления скрипта нужно будет выполнить пару команд:
# update-rc.d -f nxcdata_automount.sh remove
# rm -f /etc/init.d/nxcdata_automount.sh


В случае монтирования диска не через VMWare Shared Folders, а напрямую следует выполнить действия аналогичные как и при монтировании через VMWare Shared Folders, но с учётом того, что в системе появляется полноценный второй диск. Как узнать букву диска?

Большинство блочных устройств Linux подключаются через интерфейс SCSI, поэтому в большинстве случаев диски будут начинаться с букв sd. Третья буква в имени диска означает его порядковый номер в системе и обозначается по алфавиту: sda — первый диск, sdb — второй диск, sdc — третий и так далее. Дальше следует цифра, которая определяет номер раздела на диске: sda1, sda2 и так далее. Самый простой способ увидеть все подключенные диски — посмотреть содержимое каталога /dev/ и отфильтровать устройства sd:

$ ls -l /dev/ | grep sd

Например, нам нужно подключить диск sdb1 с файловой системой NTFS.

Создадим директорию и смонтируем в неё диск:
# mkdir /mnt/sdb1
# mount -t ext4 /dev/sdb1 /mnt/sdb1


Создадим директорию для данных, выставим ей права и пользователя:
# mkdir /mnt/sdb1/nxcdata & chmod 770 /mnt/sdb1/nxcdata & chown -R www-data:www-data /mnt/sdb1/nxcdata

Далее необходимо так же создать скрипт для автомонтирования и откорректировать команду монтирования в скрипте (примеры подключения диска с NTFS и EXT4 в скрипте уже есть и закомментированы) и добавить скрипт в автозагрузку.

B cоздаём символьную ссылку на директорию с данными:
# ln -s /mnt/sdb1/nxcdata /mnt/nxcdata/nxcdata

По сути, вся эта морока с кучей директорий nxcdata призвана для одного: обеспечить простой перенос директории с данными в будущем — не нужно будет править конфигурацию в движке Nextcloud и вообще лезть в него — всё, что нужно будет сделать — подключить новый диск, перекопировать на него данные и пересоздать символьную ссылку, ведущую к новой директории с данными. При этом, все действия не выходят за каталог /mnt. Так всё усложнённо получилось эволюционно, просто я не захотел терять наработанные решения.

Как лучше выносить данные вне виртуальной машины? Поделюсь опытом на каком варианте я остановился и почему.

USB накопители автоматически захватывались при загрузке виртуальной машины, корректно и полноценно пробрасывались внутрь и всегда всё работало, но только до того момента как накопитель по какой-то причине не отключался от системы. Помогала перезагрузка или физическое отключение и подключение диска. Решение оказалось ненадёжным. С флешками такой проблемы не было, но меня категорически не устраивал их объём и скорость работы. Возможно стоило попробовать внешний накопитель с автономным питанием.

Проброс директории через VMWare Shared Folders работал стабильно и отлично. Такое решение полностью удовлетворило задачу синхронизации двух смартфонов. Всё отработало несколько дней, были прокачаны десятки гигабайт данных. Однако, когда я решил добавить в облако данные с компьютера, то внезапно обнаружилась проблема, связанная с длинными путями и именами файлов. В теории ограничение на длину имени файла или папки в NTFS составляет 255 символов, но на практике Windows API ограничивает до 244 символов. В теории ограничение на длину пути к файлу или папке в NTFS составляет 32767 символов, но на практике Windows API ограничивает до 245 символов. Учитывая то, что я большой любитель структурировать информацию, длина пути у меня может быть очень большой. Несокращённое название книг так же может легко составлять 100-150 символов с учётом пробелов. Данное ограничение – известная проблема VMWare Shared Folders, которая не вылечилась даже при использовании Windows 10 с всякими хитроумными ключами в реестре для снятия ограничения в 255 символов. Возможна причина в ограничениях vmhgfs. От этого удобного способа подключения пришлось отказаться. Причина установлена точно – проблема в виртуальной файловой системе, которая используется в механизме VMWare Shared Folders.

Следующее решение – подключение жесткого диска напрямую к виртуальной машине. Тут тоже не выходило всё гладко. Структура данных (или файловая система, причём это проявлялось и для NTFS и для EXT2/3/4) постоянно ломались то ли при «захвате» диска или его раздела софтом виртуальной машины, то ли при возврате его в хостовую систему даже если я переводил весь диск в режим offline на хостовой системе. При некоторых режимах я не то, чтобы записывать или читать данные — я даже не мог нормально отформатировать проброшенный жесткий диск или раздел. Однако работоспособный режим удалось найти: к виртуальной машине подключался физический жесткий диск с одним разделом, отформатированный в NTFS, в определённом режиме подключения: SATA/Independent/Persistent/Use individual partition. На жестком диске в должна находиться папка nxcdata, содержащая данные.



Настройка доступа к виртуальной машине Nextcloud из локальной сети


У нас нет проблем с открытием сайтов внутри виртуальной машины или с хостовой системы. Но как открыть созданный сайт с другого компьютера в локальной сети? Посмотрим на структуру нашей сети, изображённой ниже.



На картинке видно, что маршрутизатор подключен к интернету напрямую и сконфигурирован так, что автоматически раздаёт IP адреса подключенным устройствам в диапазоне 192.168.0.2-192.168.0.254. Адрес 192.168.0.2 получил наш компьютер, а 192.168.0.3 – второй компьютер, на котором мы делаем сервер. Однако на втором компьютере установлен софт виртуализации, который создал свой виртуальный маршрутизатор и сконфигурировал его DHCP на подсеть 192.168.233.0/24. Наш виртуальный сервер получил IP 192.168.133.138.

Я без проблем могу открыть сайт внутри виртуальной машины 192.168.233.138. Я без проблем могу открыть сайт с машины 192.168.0.3 просто введя нужный IP адрес в браузере – софт виртуализации уже позаботился о правильном конфигурировании сетевого окружения на хостовой машине. Но как мне добраться до сайта с компьютера 192.168.0.2? Если я введу IP адрес 192.168.233.138, то мне ничего не откроется, так как ни мой компьютер, ни реальный маршрутизатор ничего не знают об этой подсети. Если я введу адрес 192.168.0.3, то мне так же ничего не откроется, так как на этом компьютере реально нет никакого сайта – он внутри его виртуальной машины.

Для решения этого вопроса нужно настроить виртуальный маршрутизатор компьютера 192.168.0.3. Мы уже знаем, что обращение к сайтам идёт по портам 80 и 443. При обращении на эти порты к машине 192.168.0.3 нужно построить маршрутизацию так, чтобы запросы переправлялись на виртуальную машину 192.168.233.138. К счастью для этого у нас есть доступные инструменты. В VMWare Workstation есть инструмент Virtual Network Editor, который можно открыть из меню виртуальной машины (Edit -> Virtual Network Editor).



Этот инструмент позволяет довольно гибко управлять сетевыми параметрами. Нам нужно выделить виртуальную сетевую карту VMNet8 и щелкнуть по ставшей доступной кнопке «NAT Settings…». В открывшемся окне нужно добавить правила для создания нужной нам маршрутизации.



Указываем порт хостовой системы и затем прописываем IP адрес и порт виртуальной машины, куда следует перенаправлять запросы. Для проброса HTTPS траффика необходимо указать порт 443 хостовой системы и порт 443 и адрес 192.168.233.138 виртуальной машины. После создания правил нажимаем «OK» во всех окнах – виртуальное сетевое окружение переконфигурируется автоматически.

После этих изменений наши сайты начнут открываться и с машины 192.168.0.2 при обращении к адресу 192.168.0.3.

Подобные настройки для проброса портов есть не только у VMWare, но и у VirtualBox (Настройки → Сеть → выбрать требуемый адаптер → Дополнительно → Проброс портов). Однако в процессе экспериментов по подключению жесткого диска к этому этапу у меня оказался установленным бесплатный VMWare Player, в котором Virtual Network Editor не было. В интернете про проброс портов для VMWare Player я ничего не нашёл и пришлось воспользоваться пробной версией VMWare Workstation – при установке продукта даётся 30 дней его бесплатного использования. Через 30 дней продукт можно удалить, почистить реестр и установить заново, но такое внимание к серверу как-то избыточно и явно нежелательно. И тогда я пошёл на небольшую (или большую) хитрость. В наборе файлов VMWare Workstation присутствует утилита vmnetcfg, которая по сути и запускается через пункт Virtual Network Editor. Однако в наборе файлов VMWare Player её не было. Но при установке VMWare Player как-то же конфигурирует своё сетевое окружение? Я просто взял эту утилиту и скопировал в папку с VMWare Player, после чего запустил. Удивительно, но всё получилось. Возможно, тонкие сетевые настройки в среде VMWare Player работать не будут, но проброс портов обеспечивается, а большего мне и не нужно.

Для доступа к нашему серверу из интернета нужно аналогично пробросить порты на маршрутизаторе, который подключен к интернету. В прошивках подавляющего большинства маршрутизаторов есть секция Port Forwarding, в которой и можно настроить маршрутизацию, указав внешний порт и порт и IP адрес внутренней машины. Однако есть небольшой нюанс. Если провайдер нам выдал реальный IP адрес или мы его купили у него, то тогда проблем не будет – с компьютера из любой точки планеты вводим этот IP адрес, реальный маршрутизатор перенаправит траффик на компьютер с виртуальной машиной, на котором виртуальный маршрутизатор перенаправит траффик непосредственно в виртуальную машину. А вот что делать тому, у кого нет возможности получить реальный IP адрес и он получает динамические адреса или оказывается за NAT провайдера, получая «серые» IP адреса? Мне такую задачу решать не пришлось, так как у меня есть статичный «белый» IP. Тому, кому придётся решать такую задачу так или иначе придётся разбираться с этой проблемой. Я бы советовал посмотреть в сторону dyndns или freedns.afraid.org в случае динамических адресов, либо купить дешевый VDS попробовать придумать какую-то маршрутизацию самому, так как в любом случае без внешнего сервера с статичным IP адресом подобную проблему не решить.

После конфигурирования маршрутизации я зафиксировал IP адреса компьютеров 192.168.0.3 и 192.168.233.138, прописав их в настройках сетевых карт указанных машин вручную для того, чтобы исключить их автоматическое переназначение.



Настройка Nextcloud


Теперь пришла пора открыть в браузере https:// 127.0.0.1/nextcloud внутри виртуальной машины, https:// 192.168.233.138/nextcloud с хостовой системы или, исходя из вышеописанной настроенной маршрутизации, https:// 192.168.0.3/nextcloud с любого компьютера в локальной сети.

Далее задаём логин/пароль для администратора, доступ к ранее созданной БД, а в качестве места хранения указываем полный путь к директории nxcdata: /mnt/nxcdata/nxcdata. Данный этап настройки ничем не отличается от установки какого-нибудь сайта.

В настройках админки я сделал следующие нехитрые изменения:

— Personal → выбрал русский язык и указал e-mail для администратора user@localhost
— Администрирование → Общий доступ → отключил все пункты
— Администрирование → Usage survey → отключил все пункты
— Администрирование → Дополнительные настройки → Управление файлами: «Максимальный размер загружаемого файла» установил в 25 GB
— Пользователи → создал группу users и добавил в неё нового пользователя user

После настройки нужно включить кеширование.

Открываем файл:
# nano /var/www/nextcloud/config/config.php

И в самый конец, перед «);» добавляем нижеследующее:

'memcache.local' => '\OC\Memcache\Memcached',
'memcache.distributed' => '\OC\Memcache\Memcached',
'memcached_servers' => array(
array('localhost', 11211),
),


Теперь нужно разрешить внешний доступ к сайту на уровне его «движка».

Открываем файл:
# nano /var/www/nextcloud/config/config.php

В секцию trusted_domains нужно в массив IP адрес сервера, добавить адрес, на котором установлен Nexcloud. Секция trusted_domains в нашем случае будет выглядеть следующим образом:

'trusted_domains' =>
array (
0 => '127.0.0.1',
1 => '192.168.233.138',
),


Теперь можно проверить работоспособность сервиса – открываем сайт и авторизуемся под пользователем user. Если авторизация прошла успешно, то значит сервис готов к бою – можно ставить приложение для синхронизации на компьютеры и смартфоны, для доступа ввести IP адрес 192.168.0.3 и реквизиты доступа аккаунта, созданные под каждое устройство.
К счастью или к сожалению, мне не пришлось пользовался всем потенциалом созданного сервиса, так как изначально мне нужна была система резервного копирования с верификацией и стартово я вообще хотел обойтись только subversion, но скорость коммитов особенно большого количества мелких файлов меня сильно опечалила. Я сделал всё на вырост, но попользоваться этим так и не собрался, а потом стало как-то совсем не до облака.

Более детальный обзор по использованию сервиса сделал пользователь wtigga в конце 2017 года в своей статье «Чем загрузить VPS: своё «облако» Nextcloud». В статье, с точки зрения пользователя, даётся обзор более нового сервера Nextcloud, 12-ой версии.



Дополнительная «тонкая» настройка Nextcloud


В процессе эксплуатации облака в течение первого месяца работы всплыли некоторые проблемы, которые мне пришлось решить с помощью сообщества или самостоятельно. Надо сказать, что я использовал сервис очень усиленно и по сути проверил его на стрессоустойчивость. Синхронизировать за вечер с телефонов несколько гигабайт данных и до миллиона мелких файлов с компьютера – это было обычное дело. В общем, сервис произвёл на меня очень положительное впечатление.

Я бы не сказал, что нижеизложенные решения правильны и красивы, но эти костыли работают по крайней мере для версии 11.0.2, иначе сервисом пользоваться было бы невозможно. В версии 12.х возможно что-то было улучшено и исправлено, поэтому я бы не рекомендовал эти настройки прописывать сразу в рамках стартовой настройки, в то время как для линейки 11.x их можно применять сразу.

Проблема 1

При синхронизации возникает ошибка типа «file is locked». Синхронизация останавливается. Проблема известна — необходимо очистить содержимое таблицы oc_file_locks выполнив из консоли mysql (при авторизации пользователя nextcloud) к ней следующий запрос:
mysql > DELETE FROM oc_file_locks WHERE 1

Так как такие ошибки нередки, то я не придумал ничего лучше, как создать скрипт и положить его прямо в папку суперпользователя:
# nano /root/empty_oc_file_locks

Содержимое скрипта:

#!/bin/bash
mysql -unextcloud > -pnc123 -D nextcloud  <<MY_QUERY
DELETE FROM oc_file_locks WHERE 1
MY_QUERY


Скрипт можно выполнять вручную, но это же не наш метод. Я решил запускать его автоматически каждые 15 минут используя cron (https://ru.wikipedia.org/wiki/Cron ).
Для этого нужно создать файл:
# nano /root/crontab

Со следующим содержимым:

*/15 * * * * root bash /root/empty_oc_file_locks


Теперь нужно внести изменения в планировщик:
# crontab /root/crontab

Проверить наличие изменений можно так:
# crontab -l

Проблема 2

При синхронизации по webDAV в логах (смотреть в панели администрирования, авторизовавшись администратором) могут появляться следующие ошибки:

Error PHP reset() expects parameter 1 to be array, null given at /var/www/nextcloud/apps/files_versions/lib/Storage.php#783
Error PHP ksort() expects parameter 1 to be array, null given at /var/www/nextcloud/apps/files_versions/lib/Storage.php#782
Error PHP Invalid argument supplied for foreach() at /var/www/nextcloud/apps/files_versions/lib/Storage.php#759
Error PHP Undefined index: by_file at /var/www/nextcloud/apps/files_versions/lib/Storage.php#759
Error PHP Undefined index: all at /var/www/nextcloud/apps/files_versions/lib/Storage.php#757


На этот раз сообщество ничем не помогло и пришлось вести следствие в одиночку. Причина крылась в ошибке «Undefined index… Storage.php#757», которая каскадно тянет ещё несколько ошибок. Смотрим на код этого файла. Вся проблема оказалась в квоте. На этой строчке в коде (Storage.php#757) вычисляется свободное место с учётом объёма архивных файлов. Что-то идёт не так при вычислении, хотя квота задана «неограничено». Для исправления ошибки в панели администрирования я задал «бесконечную, но числовую» квоту для каждого пользователя, например, 100TB.

Проблема 3

Проблема с синхронизацией файлов .htaccess – они просто не синхронизируются! Причём я был не одинок, на некоторых форумах задавали подобные вопросы. Однако готового решения я не встретил. Пришлось опять думать самому. В результате гугления, просмотра логов, анализа кода не придумал ничего лучше, как подправить файл движка nextcloud.
В файле /var/www/nextcloud/lib/private/Files/filesystem.php ищем следующую строку:

$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', array('.htaccess'));


И приводим её к следующему виду:

$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', array(''));




Защита для Nextcloud


Защитить наш сервис от подбора паролей к админке можно с помощью fail2ban. Для этого нужно описать характерное выражение, встречающееся в логах nextcloud при неудачной авторизации, по которому будет срабатывать соответствующий триггер.

Создаём файл:
# nano /etc/fail2ban/filter.d/nextcloud.conf

С нижеприведённым содержимым:

[Definition]
failregex={«reqId»:".*",«remoteAddr»:".*",«app»:«core»,«message»:«Login failed: '.*' \(Remote IP: ''\)»,«level»:2,«time»:".*"}
ignoreregex =

Открываем файл:
# nano /etc/fail2ban/jail.local

И в конец файла добавляем нижеприведённое:

# выявляем неудачные попытки ввода пароля к nextcloud
[nextcloud]
enabled = true
port = http,https
protocol = tcp
filter = nextcloud
logpath = /var/log/nextcloud.log


Перезагружаем сервис:
# service fail2ban restart

Проверяем наличие активного фильтра:
# fail2ban-client status nextcloud

Не забываем, что в соответствии с настройками fail2ban из предыдущей части при неудачном вводе пароля шесть раз подряд в течение 12 часов ваш IP заблокируется ни много ни мало на 30 дней. Я как-то потратил два вечера из-за ошибочного ввода пароля на одном из телефонов, пока не выяснил этот простой факт в логах системы.



Синхронизация с облаком смартфонов


Для синхронизации содержимого телефонов, работающих под Android, существует замечательное приложение FolderSync. Программа полностью оправдывает свою небольшую цену.

Для начала необходимо создать новую учётную запись, в которой в качестве адреса сервера указать https:// 192.168.0.3/nextcloud, ввести логин и пароль от предварительно созданной учётной записи и разрешить самоподписной сертификат. Нажимаем кнопку «Тест» и убеждаемся, что соединение с сервером в порядке.

Далее нужно создать задание. В задании указываем ранее созданную учётную запись и выбираем тип синхронизации – «На удалённую папку». Указываем удалённую папку (создать её можно прямо из приложения» и выбираем локальную папку для синхронизации. Расписание я установил в 2 часа ночи каждый день. В настройках синхронизации у меня было включено «Синхронизация подпапок» и «Синхронизация включенных папок», так же я выбрал опцию всегда заменять старые файлы и в случае конфликтов разрешил по умолчанию использовать локальный файл. В разделе «Соединения» я отключил все соединения кроме Wi-Fi, причём прописал SSID своей домашней Wi-Fi сети в раздел «Разрешённые WiFi SSID’ы» — приложение будет выполнять синхронизацию только в моей домашней сети и не пытаться искать сервер в других сетях. Остальные настройки я оставил по умолчанию. Здесь же можно добавить фильтрацию. Я создал новый фильтр «Имя папки содержит» и указал значение [nosync]. Таким образом, я могу исключить из синхронизации некоторые папки в указанной локальной папке, просто добавляя в конец их названия «[nosync]».

Данная настройка была произведена для таких локальных папок как DCIM, Download, Telegram, viber, WhatsApp. Плюс пара моих пользовательских папок объёмом по нескольку гигабайт. Раз в сутки происходит синхронизация содержимого этих папок с сервером, причём старые версии файлов на сервере не удаляются, а переименовываются и перемещаются в архив. Это позволяло мне быстро восстановить случайно удалённый файл или откатить изменения в каких-то других файлах.



Синхронизация с облаком персонального компьютера


Я не считаю себя настоящим программистом. Последние десять лет я программирую на таких языках программирования, которые применяются разве что при разработке процессоров или чипсетов. Ввиду того, что я уже как лет 15 ничего не делал на Си/Си++, но что-то автоматизировать на компьютере мне требовалось, я довольно активно применял скриптовые языки типа BAT/CMD или такой софт как Sign 0f Mistery или xStarter. Когда-то я узнал и попробовал что такое AutoIt и это стало новой эрой в моей автоматизации на ПК.

После того как я убедился в стабильности и надёжности системы синхронизации на смартфонах я подумал, что неплохо было бы синхронизировать данные на своём домашнем компьютере. У Nextcloud есть свой клиент для Windows и, естественно, он стал первым кандидатом для испытаний. Синхронизировать я собирался объём данных порядка терабайта, состоявший из сотен тысяч файлов разного размера. Данные были различны: музыка, картинки, документы, электронные книги, дистрибутивы, резервные копии сайтов и прочее и подобное. Всё это разумно было бы свести к синхронизации более критических данных, например, таких как документы, но мной овладел азарт и хотелось проверить сделанный сервис на прочность.

Спустя десяток часов после начала синхронизации, а по сути первой закачки контента на сервер, клиент запнулся о файл с длинным именем. В то время на сервере я еще использовал подключение внешнего хранилища через VMWare Shared Folders и мне пришлось перепробовать с десяток клиентов, а потом ставить простые эксперименты по ручному копированию файлов на сервер, чтобы понять, что проблема – на стороне сервера. Так, спустя неделю удачного запуска сервиса, пришлось откатываться на резервную виртуальную машину и отказаться от механизма VMWare Shared Folders, начиная всё сначала. В конце концов, я убрал это узкое место на стороне сервера, протестировал надёжность решения неделей синхронизации смартфонов и решил вновь вернуться к домашнему компьютеру. На этот раз клиент не споткнулся о злополучный файл и я уже было возрадовался, однако спустя полсуток синхронизации мелких файлов клиент опять подвис. Теперь выяснилось, что слишком длинный путь именно на стороне домашнего компьютера и клиент Nextcloud не может его корректно обработать. К сожалению, с родным клиентом Nextcloud работы не получилось, да и информативность его была не совсем высока, поэтому от него пришлось отказаться.

Какое-то время я потратил на то, чтобы найти удобную программу для синхронизации, поддерживающее управление через командную строку. Мне хотелось на каждую крупную папку на компьютере сделать своё задание и запускать их в пакетном режиме. Ранее у меня уже был сделан и отработан набор BAT файлов для синхронизации, используя сценарии и управление FreeFileSync через командную строку. Проблема длинных путей или имён файлов решалась заданием локальных папок вида «\\?\D:\Info», т.е. по сути обращением к локальной папке как к сетевой. Однако, что такое webdav FreeFileSync не знает. Полных аналогов FolderSync для Windows, к сожалению, не нашлось, но не раз на форумах вместо неё рекомендовали GoodSync и, после кастинга десятка других программ, я решил попробовать его. К сожалению, GoodSync стоит на порядок дороже, но разовая трата 15$ ради сохранности своих драгоценных данных, в принципе, посильная трата. Программа имеет тестовый режим, поэтому сначала можно убедиться в её работоспособности и стабильности.

GoodSync оказался довольно дружелюбным софтом. Имеется специальная портабельная версия, которая называется GoodSync2Go. Вот она меня и заинтересовала. При установке нужно выбрать букву диска и программа устанавливается на него в папку GoodSync. Я создал папку Sync в корневом каталоге диска, допустим D, и переместил туда созданную папку GoodSync со всем содержимым.

[ Данный текст написан специально для сайта geektimes.ru автором AlexanderS.
Ссылка на источник необязательна, но его упоминание крайне желательно! ]


После установки в программе нужно создать задания: указывается локальная папка и удалённая папка для синхронизации. В параметрах задания я выбрал синхронизацию слева направо с выбором опций «Синхронное удаление» и «Сохранять предыдущие версии удалённых/заменённых файлов». В настройках левой стороны я выбрал «Безопасное копирование» и «Не создавать папку _gsdata_», правой стороны — «Безопасное копирование» и «Быстрый преданализ по временным меткам». Таким образом, создаются задания на каждую требуемую папку. Допустим так я настроил задание на папку Info и назвал его «bck_Info».
Далее в папке D:\Sync создаётся файл bck_Info.bat со следующим содержимым:

@set dir=%~dp0
@%dir%GoodSync\GoodSync2Go-v10.exe /miniwin /exit sync "%~n0"


Это скриптовый язык BAT. В первой строчке кода в переменную устанавливается текущий путь для запущенного скрипта. Вторая строчка запускает по этому пути из папки GoodSync файл GoodSync2Go-v10.exe, в котором должно выполнится задание с названием имени этого файла (bck_Info), окно выполнения задания минимизируется, по завершению задания программа должна автоматически закрыться. Я могу скопировать этот скрипт несколько раз, каждый раз меняя только его название на имя ранее созданного задания в GoodSync. Таким образом, просто щёлкая кнопкой Enter по BAT файлу я могу запускать синхронизацию нужных мне папок индивидуально.

Для добавления нового задания в FreeFileSync я мог просто скопировать xml файл сценария и вручную поправить его, т.е. запуска графической оболочки программы не требовалось вообще. В GoodSync же все задания прописываются в файле D:\Sync\GoodSync\GoodSync\Profile\jobs.tic и для добавления нового задания нужно будет отрыть программу и создать его, т.к. править этот файл несколько проблематично и неизвестно к чему это может привести.
Для синхронизации всех папок теперь можно написать простой скрипт bck_all.bat:

@set dir=%~dp0

call %dir%bck_Info.bat
call %dir%bck_Info2.bat
call %dir%bck_Info3.bat
call %dir%bck_Info4.bat

Каждая строчка скрипта просто вызывает выполнение отдельного скрипта, которое запускает синхронизацию.

Это всё очень хорошо и удобно работает, однако нет никакого контроля ошибок при синхронизации. Например, если сервер не включен, то все задания стремительно выполнятся, а я, вернувшись через час, буду думать, что синхронизация уже завершена. В то же время, логи всех заданий создаются по пути D:\Sync\GoodSync\GoodSync\Profile\*.log. Достаточно просто просмотреть лог каждой синхронизации на наличие слова «ОШИБКА» – почему-то именно так в логе сообщается о сбоях при синхронизации. Поэтому решено было написать небольшую программку для анализа этих логов после всех синхронизаций, которую запускать автоматически после выполнения синхронизаций всех папок. Программка получила гордое название log_analayser и написана на полускриптовом языке AutoIt. Если кого-то заинтересует, то скачать её полную версию можно на официальном сайте AutoIt, которая содержит нужные библиотеки, компилятор и SciTE – кроссплатформенный редактор для кода из которого можно и скомпилировать программу.

Какое время я потратил на разработку и отладку кода, в результате получился файл log_analayser.au3 со следующим содержимым:

; LOG Analyser 1.0
; Программа предназначена для анализа текстовых лог-файлов

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Field=ProductName|LOG Analyser
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Field=OriginalFilename|log_analyser.exe
#AutoIt3Wrapper_Res_Comment=Программа предназначена для анализа текстовых лог-файлов
#AutoIt3Wrapper_Res_Description=Анализ лог-файлов
;****
#AutoIt3Wrapper_Res_Language=1049
#AutoIt3Wrapper_Res_ProductVersion=1.0
#AutoIt3Wrapper_Compile_Both=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

;AutoItSetOption ("WinTitleMatchMode", 2) ; сопоставление заголовка окна с произвольным фрагментом
;#NoTrayIcon ; скрыть иконку из трея во время выполнения программы

If WinExists('[CLASS:AutoIt v3;TITLE:' & @ScriptName & ']') Then
	MsgBox(48, @ScriptName, "Позволено запускать только одну копию программы!");
	;Раскоментируйте следующую строчку если нужно активировать окно вашей программы при повторном её запуске
    ;WinActivate('Имя вашей программы')
    Exit
EndIf

AutoItWinSetTitle(@ScriptName)

#include <Array.au3>
#include <_FileDirList.au3>




; настройки
Local $msg_title = "LOG Analyser 1.0"
Local $path = @ScriptDir
Local $soft_open_log = "notepad.exe"





Local $path, $dir_mode, $word, $file_analyse_name, $file_analyse_ext, $log_path, $log_msg_on
Local $file_log, $word_detect, $file_analyse, $cnt_files, $i



;проверка и загрузка параметров
if ($CmdLine[0] < 6) then
  MsgBox(0x10, $msg_title, "Отсутствуют или недостаточно параметров!" & @CRLF & @CRLF & "Работа программы прекращена")
  Exit
else
  if (StringCompare($CmdLine[1], "file") = 0) then
    $dir_mode = 0
  elseif (StringCompare($CmdLine[1], "dir") = 0) then
    $dir_mode = 1
  else
    MsgBox(0x10, $msg_title, "Первый параметр должен принимать значения 'file' или 'dir'!" & @CRLF & @CRLF & "Работа программы прекращена")
    Exit
  endif

  $word = $CmdLine[2]

  if ($dir_mode = 0) then
    $file_analyse_name = $CmdLine[3]
  else
    $dir_analyse = $CmdLine[3]
  endif

  $file_analyse_ext = $CmdLine[4]
  $log_path = $CmdLine[5]

  if (StringCompare($CmdLine[6], "err_msg_on") = 0) then
    $log_msg_on = 1
  elseif (StringCompare($CmdLine[6], "err_msg_off") = 0) then
    $log_msg_on = 0
  else
    MsgBox(0x10, $msg_title, "Шестой параметр должен принимать значения 'log_msg_on' или 'log_msg_off'!" & @CRLF & @CRLF & "Работа программы прекращена")
    Exit
  endif

endIf



; инициализация переменных
$file_log = $log_path & "\" & "log_analyser" & "-" & @YEAR & "-" & @MON & "-" & @MDAY & "-" & @HOUR & "-" & @MIN & "-" & @SEC & ".log"
$word_detect = 0


; основной код программы
if ($dir_mode = 0) then

  $file_analyse = $file_analyse_name & "." & $file_analyse_ext
  if (_file_analyser($file_analyse, $msg_title, $word, $file_log, $word_detect) = 1) then
    $word_detect = 1
  endif

else

  ; сканирование файлов для анализа
  $dir_arr = _FileDirList($dir_analyse, "*."&$file_analyse_ext, 1, 1, 0)
  ;_ArrayDisplay($dir_arr)

  ; проверка после сканирования - проверка на наличие файлов для анализа
  if ($dir_arr = 0) then
    MsgBox(0x10, $msg_title, "Неверный путь или не обнаружены файлы для анализа!" & @CRLF & @CRLF & "Работа программы прекращена")
    Exit
  endif

  $cnt_files = $dir_arr[0]

  ; перебор анализируемых файлов
  $i = 0
  While $i <> $cnt_files
    $i = $i + 1
    $file_analyse = $dir_arr[$i]
    if (_file_analyser($file_analyse, $msg_title, $word, $file_log, $word_detect) = 1) then
      $word_detect = 1
    endif
  WEnd

endif



; обработка результатов анализа
if ($word_detect = 1) and ($log_msg_on = 1) then
  if (MsgBox (0x41034, $msg_title, "Обнаружены ошибки!" & @CRLF & "Все строки с ошибками записаны в файл: " & $file_log  & @CRLF & @CRLF & "Открыть файл с ошибками?")) = 6 then
    ShellExecuteWait($soft_open_log, $file_log)
  endif
endif

Exit





; функция выполняет построчный поиск слова в файле и возвращает переменную информирующую о наличии слова хотя бы в одной строке
; все обнаруженные строки, содержащие указанное слово, пишутся в файл лога
Func _file_analyser($file_analyse, $msg_title, $word, $file_log, $word_detect)

  Local $file1, $file2, $file_line, $write_once

  $word_detect = 0
  $write_once = 0

  $file1 = FileOpen($file_analyse, 0)

  ; проверка наличия анализируемого файла
  If $file1 = -1 Then
    FileClose($file1)
    MsgBox(0x10, $msg_title, "Отсутствует файл для анализа!" & @CRLF & @CRLF & "Работа программы прекращена")
    Exit
  EndIf

  ; построчный поиск слова в анализируемом файле
  While 1
    $file_line = FileReadLine($file1)
    If @error = -1 Then ExitLoop

    if (StringInStr($file_line, $word) <> 0) then
      $word_detect = 1

      ; проверка наличия файла для лога и его создание в случае отсутствия
      if (FileExists($file_log) = 0) then
        $file2 = FileOpen($file_log, 1)
        FileClose($file2)
      endif

      ; однакоратная запись в файл имени анализируемого файла
      if ($write_once = 0) then
        $write_once = 1
        $file2 = FileOpen($file_log, 1)
        FileWriteLine($file2, "Анализ файла: " & $file_analyse)
        FileClose($file2)
      endif

      ; вывод в лог строки с ошибкой
      $file2 = FileOpen($file_log, 1)
      FileWriteLine($file2, $file_line)
      FileClose($file2)
    endif
  WEnd

  ; если были записи в файл, то отделяем их пустой строкой от следующего массива записей
  if ($word_detect = 1) then
    $file2 = FileOpen($file_log, 1)
    FileWriteLine($file2, @CRLF)
    FileClose($file2)
  endif

  FileClose($file1)

	Return $word_detect
EndFunc

После набора кода нажимаем кнопку F7 в редакторе SciTE и получаем на выходе файл log_analayser.exe.

Программа анализирует файл на наличие какого-либо слова, при нахождении создаётся файл лога, в который копируется найденная строка, содержащая это слово.

Программа может работать в двух режимах:

— анализ конкретного файла
— анализ папки, содержащей файлы для анализа (анализируются так же все вложенные подпапки)

При консольном вызове необходимо задать шесть параметров для программы:

1 — режим работы [file = анализ файла; dir = анализ папки, содержащей файлы]
2 — ключевое слово для поиска
3 — имя файла или полного пути к папке
4 — расширения файла или файлов для анализа в папке
5 — полный путь к папке, где будет расположен лог программы
6 — отображение окна после анализа всех файлов в случае нахождения заданного слова [err_msg_on = отображать; err_msg_off = не отображать]

Таким образом, получился новый скрипт bck_auto.bat:

@echo Start Backup
@set dir=%~dp0
call %dir%bck_all.bat
log_analyser.exe dir ОШИБКА %dir%GoodSync\Profile log %dir%LOG err_msg_on
exit

Скрипт запускает файл, из которого индивидуально друг за другом вызываются задания на синхронизацию всех нужных папок, а затем вызывается анализатор логов синхронизаций, по завершении работы которого в случае ошибок показывается сообщение с предложением просмотреть строки логов, где обнаружены эти ошибки и можно понять с каким заданием случились проблемы. Эти строки пишутся в отдельный лог-файл в папке D:\Sync\LOG.
И тут меня постигла жуткая неудача. Анализатор логов не работал. Нет, он прекрасно работал на тестовых файлах, но упорно не хотел видеть ошибки в логах. Я долго не мог понять в чём причина, пока не выяснил одну жуткую вещь: мало того, что в англоязычном логе сбой выводится единственным русскоязычным словом «ОШИБКА», так ещё и кодировка этой кириллицы – Macintosh! Зачем так сделали программисты из Siber Systems я не знаю, всего скорее это результат какого-то ужасного костыля внутри софта. Ну а кто сказал, что программирование должно быть скучным?

Ничего не оставалось как подпереть один костыль другим и в результате появилась работающая конструкция:

@echo Start Backup
@set dir=%~dp0
call %dir%bck_all.bat
log_analyser.exe dir Ћ˜€ЃЉЂ %dir%GoodSync\Profile log %dir%LOG err_msg_on
exit

Однако появилась следующая проблема: сам GoodSync не удаляет файлы логов, с каждым новым выполнением задания появлялись новые файлы. И если какая-то синхронизация завершилась с ошибкой, то наш анализатор всегда будет находить этот файл и бодро рапортовать об ошибке. Поэтому перед запуском синхронизаций решено было автоматически очищать папку D:\Sync от любых файлов с логами. Для этого создан элегантный скрипт clean_logs.bat:

@echo off

set dir=%~dp0

For /R %dir% %%i in (*.log) Do (
Del /q "%%i")

@echo on

Скрипт отключает вывод каких-либо сообщений, выясняет директорию запуска скрипта, сканирует все файлы (в том числе в подпапках) пока они не закончатся и удаляет все файлы с расширением log. По окончании работы вывод сообщений включается.
Скрипт bck_auto.bat преобразился:

@echo Start Backup
@set dir=%~dp0
@call clean_logs.bat
call %dir%bck_all.bat
log_analyser.exe dir Ћ˜€ЃЉЂ %dir%GoodSync\Profile log %dir%LOG err_msg_on
exit

Всё очень отлично работает, но ведь смысл в автоматизации рутинных действий. Почему бы нельзя просто выключить компьютер на ночь и пойти спать, а он путь сам синхронизирует кучу файлов, анализирует и выключается?

Доработаем наш скрипт bck_auto.bat:

@echo Start Backup & PCOFF
@set dir=%~dp0
start MonitorOnOff.exe 0
@call clean_logs.bat
call %dir%bck_all.bat
log_analyser.exe dir Ћ˜€ЃЉЂ %dir%GoodSync\Profile log %dir%LOG err_msg_off
shutdown /s /t 0
exit

В скрипте появилось две новых строчки. Приложение MonitorOnOff просто отключает монитор (чтобы он не освещал комнату, а вручную мне его отключать каждый вечер и включать каждое утро очень лень), а команда shutdown выключает компьютер. В log_analyser изменился параметр, отвечающий за показ сообщений при нахождении ошибки – ведь после синхронизации не нужно тормозить выполнение скрипта этим сообщением, а дать возможность ему выключить компьютер.

Программа MonitorOnOff так же написана на AutoIt.

; Monitor On Off 1.0
; Программа для включения/отключения монитора

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Field=ProductName|Monitor On Off
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Field=OriginalFilename|MonitorOnOff.exe
#AutoIt3Wrapper_Res_Comment=Программа для включения/отключения монитора
#AutoIt3Wrapper_Res_Description=Программа для включения/отключения монитора
;****
#AutoIt3Wrapper_Res_Language=1049
#AutoIt3Wrapper_Res_ProductVersion=1.0
#AutoIt3Wrapper_Compile_Both=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****


;AutoItSetOption ("WinTitleMatchMode", 2) ; сопоставление заголовка окна с произвольным фрагментом
;#NoTrayIcon ; скрыть иконку из трея во время выполнения программы

If WinExists('[CLASS:AutoIt v3;TITLE:' & @ScriptName & ']') Then
  MsgBox(48, @ScriptName, "Позволено запускать только одну копию программы!");
  ;Раскоментируйте следующую строчку если нужно активировать окно вашей программы при повторном её запуске
  ;WinActivate('Имя вашей программы')
  Exit
EndIf

AutoItWinSetTitle(@ScriptName)





HotKeySet("{F10}", "_Monitor_ON")
HotKeySet("{F11}", "_Monitor_OFF")
HotKeySet("{Esc}", "_Quit")





Global Const $lciWM_SYSCommand = 274
Global Const $lciSC_MonitorPower = 61808
Global Const $lciPower_Off = 2
Global Const $lciPower_On = -1

Global $MonitorIsOff = False



if ($CmdLine[0] <> 0) then
  _Monitor_OFF()
endif



While 1
  Sleep(10)
WEnd



Func _Monitor_ON()
  $MonitorIsOff = False
  Local $Progman_hwnd = WinGetHandle('[CLASS:Progman]')

  DllCall('user32.dll', 'int', 'SendMessage', _
                                              'hwnd', $Progman_hwnd, _
                                              'int', $lciWM_SYSCommand, _
                                              'int', $lciSC_MonitorPower, _
                                              'int', $lciPower_On)
EndFunc



Func _Monitor_OFF()
  $MonitorIsOff = True
  Local $Progman_hwnd = WinGetHandle('[CLASS:Progman]')

  While $MonitorIsOff = True
    DllCall('user32.dll', 'int', 'SendMessage', _
                                                'hwnd', $Progman_hwnd, _
                                                'int', $lciWM_SYSCommand, _
                                                'int', $lciSC_MonitorPower, _
                                                'int', $lciPower_Off)
    _IdleWaitCommit(0)
    Sleep(20)
  WEnd
EndFunc



Func _IdleWaitCommit($idlesec)
  Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
  DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
  DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))

  Do
    $iSave = DllStructGetData ($LastInputInfo, 2)
    Sleep(60)
    DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
  Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec Or $MonitorIsOff = False

  Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc



Func _Quit()
  _Monitor_ON()
  Exit
EndFunc

Запущенная программа управляется тремя клавишами: F10 включает монитор, F11 – отключает, а кнопка ESC завершает работу программы и выгружает её из памяти. При задании любого параметра при запуске программы запущенная программа сразу отключит экран.

Теперь всё было хорошо – перед сном я просто запускал bck_all.bat, вместо «Выключить компьютер» и уходил спать. Монитор не освещал всю комнату, синхронизация производилась автоматически и автоматически анализировалась её успешность. Утром надо было только посмотреть содержимое папки D:\Sync\GoodSync\LOG\ на предмет хоть каких-то файлов. Но и это тоже не дело – зачем тратить время если всё хорошо? Нужно сделать анализатор лога анализатора логов и повесить его в автозагрузку системы, чтобы он срабатывал на следующий день при загрузке компьютера и тревожил моё внимание только при сбоях синхронизации. Так появилась программа check_file_exist.

; Check File Exist 1.0
; Программа предназначена для проверки наличия указанного файла

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Res_Field=ProductName|Check File Exist
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Field=OriginalFilename|check_file_exist.exe
#AutoIt3Wrapper_Res_Comment=Программа предназначена для проверки наличия указанного файла
#AutoIt3Wrapper_Res_Description=Провека существования файла
;****
#AutoIt3Wrapper_Res_Language=1049
#AutoIt3Wrapper_Res_ProductVersion=1.0
#AutoIt3Wrapper_Compile_Both=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

;AutoItSetOption ("WinTitleMatchMode", 2) ; сопоставление заголовка окна с произвольным фрагментом
;#NoTrayIcon ; скрыть иконку из трея во время выполнения программы

If WinExists('[CLASS:AutoIt v3;TITLE:' & @ScriptName & ']') Then
	MsgBox(48, @ScriptName, "Позволено запускать только одну копию программы!");
	;Раскоментируйте следующую строчку если нужно активировать окно вашей программы при повторном её запуске
    ;WinActivate('Имя вашей программы')
    Exit
EndIf

AutoItWinSetTitle(@ScriptName)

#include <Array.au3>
#include <_FileDirList.au3>





; настройки
Local $msg_title = "Check File Exist 1.0"
Local $path = @ScriptDir
Local $soft_open_dir = "explorer.exe"





Local $path, $dir_analyse, $words, $msg_open



;проверка и загрузка параметров
if ($CmdLine[0] < 5) then
  MsgBox(0x10, $msg_title, "Отсутствуют или недостаточно параметров!" & @CRLF & @CRLF & "Работа программы прекращена")
  Exit
else
  $dir_analyse = $CmdLine[1]
  $file = $CmdLine[2]

  $words0 = $CmdLine[3]
  $words1 = $CmdLine[4]

  if (StringCompare($CmdLine[5], "msg_on") = 0) then
    $msg_open = 1
  elseif (StringCompare($CmdLine[5], "msg_off") = 0) then
    $msg_open = 0
  else
    MsgBox(0x10, $msg_title, "Пятый параметр должен принимать значения 'msg_on' или 'msg_off'!" & @CRLF & @CRLF & "Работа программы прекращена")
    Exit
  endif
endIf



; сканирование директории на наличие файлов
$dir_arr = _FileDirList($dir_analyse, "*"&$file&"*", 1, 0, 0)
;_ArrayDisplay($dir_arr)

; проверка наличия файла и действия
if ($dir_arr = 0) then
  if (StringCompare($words0, "0") <> 0) then
    if ($msg_open = 0) then
      MsgBox(0x41030, $msg_title, $words0)
    else
      if (MsgBox(0x41034, $msg_title, $words0 & @CRLF & @CRLF & "Открыть папку с не обнаруженными файлами?")) = 6 then
        ShellExecuteWait($soft_open_dir, $dir_analyse)
      endif
    endif
  endif
else
  if (StringCompare($words1, "0") <> 0) then
    if ($msg_open = 0) then
      MsgBox(0x41030, $msg_title, $words1)
    else
      if (MsgBox(0x41034, $msg_title, $words1 & @CRLF & @CRLF & "Открыть папку с обнаруженными файлами?")) = 6 then
        ShellExecuteWait($soft_open_dir, $dir_analyse)
      endif
    endif
  endif
endif





Exit

По сути эта программа – немного урезанный функционал log_analyser. Программа анализирует указанную папку (без учёта подпапок) на наличие файлов и именами хотя бы частично совпадающими с указанным словом для поиска и выводит сообщение о результате проверки.

Параметры программы:

1 — полный путь к папке (без символа слеша — /)
2 — ключевое слово для поиска в именах файлов, либо полное название файла
3 — текстовая строка, выводимая при ненахождении файл, если =0 — не выводить сообщение
4 — текстовая строка, выводимая при нахождении файла, если =0 — не выводить сообщение
5 — вывод сообщения: msg_off — выводится только сообщение о наличии/отсутствии файлов, msg_on — в выведенном окне предлагается так же открыть папку, в которой обнаружены или необнаружены файлы

Теперь, для этой программы я создал скрипт Check_LOG_from_log_analyser.bat, ссылку которого разместил в обычной автозагрузке Windows:

@set dir=%~dp0LOG
start check_file_exist.exe %dir% .log 0 "Во время последней синхронизации были проблемы!" msg_on
exit

Таким образом, в финале мы получили полностью автономное решение, которое не зависит от местонахождения папки Sync и корректно отработает из любого места нашего компьютера. Решение не только работоспособно, но и стабильно – на Windows 7 х64 данный комплект скриптов отработал год и абсолютно никаких проблем с ним не возникло.

Возможно сейчас всё это кажется несколько монстрообразным, однако ничего сложно в этом нет. Если внимательно присмотреться к коду AutoIt, то базовой конструкцией является обычные циклы if-then-else-end, однотипные для любого языка программирования, в которые встроены некоторые повторяющиеся операторы и функции AutoIt, которые изучаются буквально за пару вечеров. Скриптовый язык BAT можно даже не учить, так как большинство решений типовые и уже давно описаны в интернете. Уметь пользоваться программированием не только интересно, но может быть и весьма полезно.

Ода коду от Dark Dragon




Послесловие


Если честно, я предполагал, но сам не ожидал такого объёма статей, на которые пришлось потратить до полусотни часов. Как правило, в интернете установку своего облака сводят к изречениям типа: «Да, там надо-то выполнить несколько команд». Это правда – установка тривиальная. Когда ты знаешь какие команды вводить в консоль и что они значат. Когда ты понимаешь суть маршрутизации в сети. Когда у тебя уже есть работающий сервер и когда ты понимаешь, как в него добавить хост. Когда ты знаешь, как установить сайт. То есть, для применения этих нескольких команд нужно иметь определённый багаж знаний и опыта. Цель этих трёх статей – попытка создать такой багаж, собрав необходимую достаточную информацию в одном месте и пояснить как ей правильно пользоваться. Я искренне надеюсь, что этот цикл статей поможет кому-то сделать свои первые осознанные шаги в мир свободного программного обеспечения.



Вернуться в начало, к оглавлению.



История создания домашнего облака. Часть 3. Создание персонального облака — установка и настройка Nextcloud.
Версия текста: 1.2.2.
Дата первой публикации: 08.02.2018.
Дата последней правки: 29.12.2021.

Лог обновлений
1.2.2 [29-12-2021]
Правка ссылок оглавления.

1.2.1 [15-01-2020]
Обновление оглавления.

1.2.0 [08-02-2018]
Коррекция текста.

1.1.0 [08-02-2018]
Коррекция текста.

1.0.0 [08-02-2018]
Первая версия.
Описывается установка и настройка Nextcloud 11.0.2 в виртуальной машине VMWare, конфигурация сетевого окружения VMWare и освещаются некоторые моменты настройки, проявившиеся в процессе эксплуатации Nextcloud.



Информация для администрации ресурса (подозрение на баг)
Если в какой-то тег (например, code или blockquote) в вышеприведённом тексте обернуть следующую конструкцию:
[Definition]
failregex={«reqId»:".*",«remoteAddr»:".*",«app»:«core»,«message»:«Login failed: '.*' \(Remote IP: ''\)»,«level»:2,«time»:".*"}
ignoreregex =

То закрывающий тег фильтруется и оформление применяется до конца статьи! Подобный эффект проявляется именно в этом тексте, т.к. отдельно воспроизвести эффект мне не удалось. Парную корректность тегов (открыто/закрыто) проверил — вроде бы всё нормально. Методика повторения:
— создать черновик
— скопировать исходное форматирование этой статьи и разместить в черновике
— в тексте, в разделе «Защита для Nextcloud» обернуть вышеуказанную конструкцию, например, цитатой
— эффект проявляется, в цитату попадёт весь текст до конца статьи



Теги:
Хабы:
Всего голосов 15: ↑14 и ↓1+13
Комментарии45

Публикации

Истории

Ближайшие события