Вопрос или проблема
Я знаю, о чем вы сейчас думаете “Просто используйте rsync“, но, к сожалению, эта система не имеет rsync, и я хотел бы придумать другое решение.
Настройка:
- Сервер-источник имеет папку Upload, содержащую более 140 000 файлов (без подпапок)
- Сервер-назначение нуждается в папке Upload, содержащей более 140 000 файлов
Назовем это миграцией только с помощью наклейки Post-It… Теперь, чтобы усложнить задачу, Сервер 1 каждый день получает новые файлы из-за новых загрузок или генерируемых миниатюр, поэтому та идея, которая у вас сейчас в голове “просто скопируйте файл с 1 на 2“, не сработает, так как, как только я закончу с копированием примерно 20+ ГБ, я могу начать снова, так как на сервере-источнике уже появится новый файл…
Моя идея решения
- Скопировать полную папку с источника на назначение
- Найти дату создания в сервере-назначении и использовать ее как отправную точку на сервере-источнике
- Скопировать все файлы с последней даты создания с источника на назначение (дельта)
- Настроить cron, чтобы делать это как можно чаще.
Моя проблема
find /uploads/* -mtime -1
bash: /bin/find: Слишком длинный аргумент
Теперь, прежде чем я начну писать цикл bash-скрипта, мне интересно, есть ли кто-нибудь, кто мог бы предложить другой способ сделать это без bash-скрипта… добрый старый низкоуровневый CLI.
Мне удалось найти решение, но еще не в одной строке. Я всё еще работаю над этим.
Предполагая, что вы можете доверять дате создания/изменения файловой системы, можно использовать find для генерации списка файлов, вывести это в текстовый файл, а затем с помощью цикла выполнить scp на сервер назначения. Я не могу заставить результат find правильно передавать в scp.
Я использовал вспомогальную программу sshpass, но было бы лучше использовать ключевые файлы, я знаю
Найти файлы на сервере-источнике с сервера-назначения и сохранить результат, ограничив результат только одной директорией и только файлами.
sshpass -p 'MyPassword' ssh [user@server] "find [path/to/look/in] -maxdepth 1 -mtime -1 -type f" > /tmp/last-24-hours-file-list.txt
Цикл по выходному файлу и вызов scp для каждого файла
while read filename; do sshpass -p 'MyPassword' scp -Crpv [user@server]:$filename [path/to/save/to]; done < /tmp/last-24-hours-file-list.txt
Ответ или решение
Для синхронизации двух директорий без использования rsync в условиях, описанных в вашем вопросе, я предлагаю следующий подход, который сочетает в себе эффективность и надежность.
1. Обзор задачи
Вы хотите перенести файлы из одной директории на другой сервер, при этом необходимость в синхронизации возникает из-за постоянного добавления новых файлов. Вам нужно учитывать 140 000+ файлов и избежать проблем, связанных с ошибкой "Argument list too long".
2. Решение
2.1 Копирование файлов в начальном переносе
В первую очередь, вам нужно будет выполнить однократное полное копирование всех файлов из исходной директории на целевой сервер. Это можно сделать с помощью команды scp
или sftp
. На данном этапе допустимо использовать временный метод, так как он будет только один раз.
scp -r user@source_server:/path/to/uploads/* /path/to/destination/
2.2 Определение последней даты изменения
После первого копирования необходимо определить, когда был сделан последний upload файлов на целевом сервере. Это можно сделать, выполнив команду на целевом сервере:
ls -lt /path/to/uploads/ | head -n 1
2.3 Синхронизация новых файлов
Теперь, чтобы синхронизировать новые файлы, мы можем использовать find
для создания списка файлов, которые были изменены за последнее время, и перенести их на целевой сервер. Для этого выполняем следующие действия.
- Выполните команду
find
на исходном сервере через SSH, чтобы сохранить список недавно измененных файлов.
ssh user@source_server "find /path/to/uploads -maxdepth 1 -type f -mtime -1" > /tmp/last-24-hours-file-list.txt
- Перенесите файлы, указанные в созданном списке. Используем цикл для перебора файлов:
while read filename; do
scp user@source_server:"$filename" /path/to/destination/
done < /tmp/last-24-hours-file-list.txt
2.4 Настройка автоматизации
Для автоматизации процесса вы можете использовать cron. Добавьте запись в crontab на целевом сервере, чтобы периодически выполнять синхронизацию, например, каждый час:
0 * * * * /path/to/your/script.sh
Где script.sh
— это ваш написанный скрипт, содержащий команды из вышеописанного процесса.
3. Заключение
Такой подход обеспечивает эффективную синхронизацию между серверами без использования rsync, но с применением надежных методов, таких как find
и scp
. Он также подходит для сценариев с большим количеством файлов. Применение автоматизации через cron
окончательно решает проблемы, возникающие с новыми файлами, которые появляются в процессе синхронизации.
Это решение эффективно и может быть адаптировано под ваши конкретные нужды, включая использование ключей SSH для безопасного доступа вместо sshpass
.