- Совместимость с XenForo
- 2.3.х
- Видимый копирайт
- Нет
- Русификатор
- Нет
- Доп. требования
- - Доступ по SSH / через командную строку. Скрипт отказывается работать через HTTP.
- PHP 8.0+ (в зависимости от того, что уже требуется для вашей установки XenForo).
- Столбец file_key в xf_attachment_data. Скрипт проверяет его наличие при запуске и
прерывает работу, если он отсутствует, вместо того чтобы угадывать пути.
- Примерно 100 МБ оперативной памяти на 50 000 вложений при использовании параметра --index.
- Работает с локальным хранилищем и с удаленными адаптерами Flysystem (S3, R2 и т. д.).
- Не требует установки дополнений. Автономный скрипт, размещенный в корневом каталоге форума.
Если файл вложения отсутствует, но строка в базе данных сохранилась, XenForo все равно отображает ссылку на вложение. При нажатии на нее выдается ошибка 500, а журнал ошибок заполняется следующим текстом:
Не существует встроенного способа массового поиска таких случаев, а также способа отличить действительно потерянное вложение от того, файл которого все еще находится в хранилище под устаревшим ключом.
Это происходит после восстановления базы данных, миграции хранилища, неудачной синхронизации S3/R2, частичного восстановления резервной копии или просто из-за того, что в течение многих лет файлы не удалялись.
Что это делает
Каждое вложение классифицируется одним из трех способов:
Три режима
Поместите скрипт в корневую папку вашего форума, рядом с index.php. Затем:
Этот скрипт доступен только для чтения и ничего не меняет. --index выполняет одно рекурсивное перечисление вашего хранилища и отвечает на все запросы из памяти — при использовании удаленного хранилища это позволяет сократить ~200 000 сетевых запросов до ~200 вызовов списка.
Просмотрите CSV-файл. Затем сделайте резервную копию:
Восстановить без удаления:
Восстановить и удалить нерабочие строки:
Безопасность
Этот инструмент может удалять строки в базе данных, поэтому он разработан с учетом того, что может ошибаться.
Важное примечание по совместимости
XenForo получает сохраненный путь из
Скрипт проверяет наличие столбца при запуске и прерывает работу, если столбец отсутствует, а не пытается угадать.
Тестирование
Протестировано на реальном форуме с 201 465 вложениями на XenForo 2.3 с удаленным хранилищем на другом хосте, а также на наборе фикстур, охватывающем перелинковку, отказ от повторного использования идентификаторов, поддержание attach_count, обнаружение «сиротских» вложений, идемпотентность и все перечисленные выше меры предосторожности. Полное сканирование 200 тысяч строк занимает менее двух минут.
Код:
League\Flysystem\FileNotFoundException: File not found at path: attachments/236/236888-0dcb....data
src/XF/Pub/View/Attachment/View.php:27
Это происходит после восстановления базы данных, миграции хранилища, неудачной синхронизации S3/R2, частичного восстановления резервной копии или просто из-за того, что в течение многих лет файлы не удалялись.
Что это делает
Каждое вложение классифицируется одним из трех способов:
- OK — файл находится именно там, где его ожидает XenForo.
- RELINK — файл отсутствует по ожидаемому пути, но файл с этим data_id существует под другим file_key и его md5 совпадает с сохраненным file_hash. Загрузка прошла успешно, но указатель в базе данных устарел. Можно восстановить без потери данных.
- ОТСУТСТВУЕТ — файл отсутствует или существует кандидат, чей md5 не совпадает, то есть идентификатор был повторно использован при более поздней загрузке и этот файл принадлежит кому-то другому. Восстановить ничего не удастся.
Три режима
- Сканирование — обходит базу данных с запросом «где находится файл?» и записывает данные в CSV. Только для чтения.
- «Сироты» — обратный режим. Обходит хранилище с запросом «какой строке принадлежит этот файл?», находя файлы, оставшиеся после отката базы данных, которые не видны при обычном сканировании, поскольку этих строк больше не существует. Только для чтения.
- Применить — обрабатывает CSV-файл со сканированием, повторно сверяет каждую строку с хранилищем, а затем исправляет ошибки. Удаляет только по вашему прямому запросу.
Поместите скрипт в корневую папку вашего форума, рядом с index.php. Затем:
Код:
php xf-missing-attachments.php --index --report=scan.csv
Просмотрите CSV-файл. Затем сделайте резервную копию:
Код:
mysqldump YOUR_DB xf_attachment xf_attachment_data > attach-backup.sql
Код:
php xf-missing-attachments.php --apply=scan.csv --index
Код:
php xf-missing-attachments.php --apply=scan.csv --index --delete
Этот инструмент может удалять строки в базе данных, поэтому он разработан с учетом того, что может ошибаться.
- При сканировании данные не записываются. Для удаления требуется отдельный запуск, отдельный флаг и CSV-файл, который вы уже успели прочитать.
- Каждая строка повторно проверяется в реальном хранилище непосредственно перед внесением изменений. Устаревший или отредактированный вручную CSV-файл не может привести к повреждению данных.
- При пустом индексе происходит сбой. Если хранилище недоступно или указан неверный префикс, каждая строка будет отображаться как MISSING. Это фатальная ошибка, и параметр --force ее не отменяет.
- Защита от превышения лимита. Запрос на удаление более 20 % всех вложений отклоняется — это означает ошибку в хранилище, а не потерю данных.
- Count guard. --max-delete (по умолчанию 2000) блокирует неожиданно большие запросы на удаление.
- Удаления проходят через уровень сущностей, поэтому attach_count поддерживается собственным обработчиком вложений XenForo для каждого типа контента, включая контент из других дополнений.
- Неизвестные аргументы отклоняются, а не игнорируются без предупреждения.
- Отчеты не могут быть записаны в путь, доступный через веб-интерфейс — в них перечисляются все вложения на вашем форуме. Они сохраняются в папке internal_data/attachment-audit/.
- Отказывается работать по протоколу HTTP.
[ATTACH], к которому больше нет прикрепленного файла, отображается как пустое место, поэтому пост сохраняет свой текст, но теряет поврежденное изображение. Ни одна тема не удаляется. О потерянных файлах в хранилище сообщается, но они никогда не удаляются — удаление таких файлов привело бы к уничтожению единственной оставшейся копии.Важное примечание по совместимости
XenForo получает сохраненный путь из
xf_attachment_data.file_key, не file_hash. Оба варианта представляют собой 32-символьные шестнадцатеричные строки, поэтому их легко перепутать, и в результате каждое вложение получает статус MISSING. Если вы пишете для этого собственный инструмент, то попадаете в ловушку.Скрипт проверяет наличие столбца при запуске и прерывает работу, если столбец отсутствует, а не пытается угадать.
Тестирование
Протестировано на реальном форуме с 201 465 вложениями на XenForo 2.3 с удаленным хранилищем на другом хосте, а также на наборе фикстур, охватывающем перелинковку, отказ от повторного использования идентификаторов, поддержание attach_count, обнаружение «сиротских» вложений, идемпотентность и все перечисленные выше меры предосторожности. Полное сканирование 200 тысяч строк занимает менее двух минут.