Перейти к основному содержанию

OwnCloud — долгая синхронизация файлов

Owncloud

Сегодня у нас продолжение истории с синхронизацией файлов в OwnCloud. 

OwnCloud — это свободное и открытое веб-приложение для синхронизации данных и совместной работы с файлами в стиле Dropbox. Замечательный инструмент для создания личного, семейного или корпоративного файлового хранилища.

Ранее я уже решал проблему с синхронизацией файлов:

OwnCloud не синхронизирует файлы

Проблема была решена синхронизацией файлов для всех пользователей через cron:

0  7,19  *  *  * /usr/bin/php -f /var/www/owncloud/occ files:scan --all

Синхронизация перестала работать с ошибкой:

Lost connection to LDAP server

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

OwnCloud при синхронизации файлов теряет соединение с LDAP

0  7,19  *  *  * /usr/bin/php -f /var/www/owncloud/occ user:home:list-users /var/www/owncloud/data/ | sed 's/^ *- //' | xargs -I {} /usr/bin/php -f /var/www/owncloud/occ files:scan {}

Какое-то время всё работало. Затем, файлов стало больше и всплыла новая проблема.

Exception during scan: Doctrine\DBAL\Exception\LockWaitTimeoutException: An exception occurred while executing 'UPDATE `oc_filecache` SET `size`=? WHERE (`size` <> ? OR `size` IS NULL) AND `fileid` = ? ' with params [1000025263, 1000025263, "741856865"]:

SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

Оказалось, что скрипт работал долго и cron запускал второй экземпляр, затем третий. Эти экземпляры создавали нагрузку на БД и конфликтовали друг с другом. Пришлой уйти от однострочника и переделать всё это на bash скрипт.

В кроне под www-data запускаем (у вас свои временные метки, хоть каждый час):

0  7,19  *  *  * /opt/cron/owncloud_scan.sh 2>/var/log/owncloud/cron_errors.log

Для ошибок создаём файл /var/log/owncloud/cron_errors.log, для логов: /var/log/owncloud/owncloud_scan.log. И делаем скрипт /opt/cron/owncloud_scan.sh:

#!/bin/bash

# Конфигурация
LOG_FILE="/var/log/owncloud/owncloud_scan.log"
OWNCLOUD_PATH="/var/www/owncloud"
REQUIRED_USER="www-data"
LOCK_FILE="/tmp/owncloud_scan.lock"

# Функция для логирования с временной меткой
log() {
   echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" >> "$LOG_FILE"
}

# Проверяем, запущен ли скрипт от правильного пользователя
if [ "$(whoami)" != "$REQUIRED_USER" ]; then
   echo "Ошибка: Этот скрипт должен запускаться от пользователя $REQUIRED_USER" >&2
   echo "Используйте: sudo -u $REQUIRED_USER $0" >&2
   exit 1
fi

# Создаем директорию для логов, если её нет
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || {
   echo "Ошибка: Не удалось создать директорию для логов" >&2
   exit 1
}

# ПРОВЕРКА ЧЕРЕЗ LOCK ФАЙЛ
if [ -f "$LOCK_FILE" ]; then
   # Читаем PID из lock файла
   LOCK_PID=$(cat "$LOCK_FILE" 2>/dev/null)

   # Проверяем, существует ли процесс с этим PID
   if [ -n "$LOCK_PID" ] && kill -0 "$LOCK_PID" 2>/dev/null; then
       # Проверяем, что это действительно наш скрипт
       # (проверяем по имени скрипта в командной строке процесса)
       if ps -p "$LOCK_PID" -o cmd= 2>/dev/null | grep -q "owncloud_scan"; then
           log "Скрипт уже запущен (PID: $LOCK_PID). Пропускаем выполнение."
           exit 0
       else
           # Это не наш процесс, удаляем устаревший lock файл
           rm -f "$LOCK_FILE"
       fi
   else
       # Процесс не существует, удаляем устаревший lock файл
       rm -f "$LOCK_FILE"
   fi
fi

# Создаем lock файл с PID текущего процесса
echo $$ > "$LOCK_FILE"

# Функция для очистки lock файла при выходе
cleanup() {
   rm -f "$LOCK_FILE"
}

# Устанавливаем обработчики для гарантированного удаления lock файла
trap cleanup EXIT
trap cleanup INT TERM

log "Начало сканирования"

# Проверяем наличие occ
if [ ! -f "$OWNCLOUD_PATH/occ" ]; then
   log "Ошибка: Файл $OWNCLOUD_PATH/occ не найден"
   exit 1
fi

# Проверяем наличие data директории
if [ ! -d "$OWNCLOUD_PATH/data" ]; then
   log "Ошибка: Директория $OWNCLOUD_PATH/data не найдена"
   exit 1
fi

# Получаем список пользователей
USERS=$("/usr/bin/php" -f "$OWNCLOUD_PATH/occ" user:home:list-users "$OWNCLOUD_PATH/data/" 2>/dev/null | sed 's/^ *- //')

if [ -z "$USERS" ]; then
   log "Не найдено пользователей для сканирования"
   exit 0
fi

# Сканируем файлы каждого пользователя
while read -r user; do
   if [ -n "$user" ]; then
       log "Сканирование пользователя: $user"
       "/usr/bin/php" -f "$OWNCLOUD_PATH/occ" files:scan "$user" >> "$LOG_FILE" 2>&1
       SCAN_RESULT=$?
       if [ $SCAN_RESULT -ne 0 ]; then
           log "Ошибка при сканировании пользователя $user (код: $SCAN_RESULT)"
       fi
   fi
done <<< "$USERS"

log "Сканирование завершено"
exit 0

Неделя — полёт нормальный.

Теги

 

Похожие материалы

OwnCloud — установка на Ubuntu 20.04

OwnCloud — это свободное и открытое веб-приложение для синхронизации данных и совместной работы с файлами в стиле Dropbox. Замечательный инструмент для создания личного, семейного или корпоративного файлового хранилища.

Запуск BAT скрипта при логине на сервер один раз

Настроим автозапуск BAT скрипта при логине юзера на сервер. Сделаем так, чтобы скрипт запускался только один раз, а при последующих входах запускаться не будет.

Теги

OwnCloud при синхронизации файлов теряет соединение с LDAP

Столкнулся с проблемой, OwnCloud при синхронизации файлов из внешнего хранилища, подключенного по SMB из Windows сервера, получает ошибку: Lost connection to LDAP server.

Теги