site_sync.sh

Горячая копия сайта на другом сервере: дамп БД по ssh + rsync файлов + (опционально) развёртывание дампа. Запускается из cron.

Что делает

  1. Предпроверка: ssh-доступ, наличие mysqldump/pg_dump, каталога сайта и временного каталога на источнике; при RESTORE=yes — доступ к локальной БД.
  2. Дамп на источнике (если DB_DUMP=yes): дамп БД с gzip во временный файл. Если gzip на источнике нет, дамп делается без сжатия (см. REMOTE_COMPRESS). Пароль БД не передаётся в аргументах и не виден в ps.
  3. Скачивание: rsync во временный .partial, проверка размера и gzip -t (несжатый дамп сжимается локально), затем переименование в <БД>_ГГГГ-ММ-ДД_ЧЧММСС.sql.gz. Временный дамп на источнике удаляется.
  4. Ротация: хранятся KEEP_DUMPS последних дампов.
  5. Файлы: rsync каталога сайта (с опциональным --delete и исключениями).
  6. Развёртывание (если RESTORE=yes): заливка скачанного дампа в локальную БД.

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

Сайт без БД: при DB_DUMP='no' шаги с дампом, ротацией и развёртыванием пропускаются, переносятся только файлы.

Требования

На сервере, где запускается скрипт (приёмник)

На сервере-источнике

Быстрый старт

cp site_sync.conf.example /etc/site_sync.conf
chmod 600 /etc/site_sync.conf
nano /etc/site_sync.conf          # заполнить параметры

chmod +x site_sync.sh
./site_sync.sh -c /etc/site_sync.conf --check   # проверка без изменений
./site_sync.sh -c /etc/site_sync.conf           # первый боевой запуск

Без аргументов скрипт читает site_sync.conf из своего каталога. Конфиг можно передать флагом -c или первым позиционным аргументом.

--check проверяет конфиг, ssh-подключение, команды и каталоги, но ничего не скачивает и не создаёт.

Минимальный конфиг для сайта без БД

SSH_HOST='example.com'
SSH_USER='deploy'
SSH_AUTH='key'
SSH_KEY='/root/.ssh/id_ed25519'
DB_DUMP='no'
REMOTE_SITE_DIR='/var/www/mysite'
LOCAL_SITE_DIR='/var/www/mysite'
RSYNC_DELETE='yes'
LOG_FILE='/var/log/site_sync_mysite.log'

Параметры конфига

Конфиг — обычный bash-файл (подключается через source). Значения с пробелами берите в одинарные кавычки. Полный пример с комментариями: site_sync.conf.example.

SSH

ПараметрПо умолчаниюОписание
SSH_HOST, SSH_USER— (обязательно)Сервер-источник и пользователь
SSH_PORT22Порт
SSH_AUTHkeykey / plain / sshpass (см. ниже)
SSH_KEYпустоПуть к приватному ключу (пусто = ключи по умолчанию)
SSH_PASS—Пароль для plain
SSH_PASS_FILE—Файл с паролем (1 строка) для sshpass
SSH_STRICT_HOST_KEYaccept-newaccept-new / yes / no. accept-new требует OpenSSH 7.6+
SSH_KNOWN_HOSTSпустоСвой файл known_hosts
SSH_CONNECT_TIMEOUT20Таймаут подключения, сек

БД на источнике

ПараметрПо умолчаниюОписание
DB_DUMPyesno — дамп БД отключён, переносятся только файлы (сайты без БД). Параметры БД, LOCAL_BACKUP_DIR и RESTORE тогда не нужны (RESTORE игнорируется с предупреждением)
REMOTE_DB_TYPEmysqlmysql (MySQL/MariaDB) или pgsql
REMOTE_DB_HOSTlocalhostХост БД, как он виден с источника
REMOTE_DB_PORT3306 / 5432Порт
REMOTE_DB_NAME, REMOTE_DB_USER— (обязательно при DB_DUMP=yes)Допустимы только A-Z a-z 0-9 _ . -, не должны начинаться с -
REMOTE_DB_PASSпустоПароль БД
REMOTE_DUMP_OPTSmysql: --single-transaction --routines --triggers --events
pgsql: --no-owner --no-privileges
Параметры дампа
REMOTE_DUMP_BINmysqldump / pg_dumpНапример mariadb-dump для MariaDB 11+
REMOTE_COMPRESSautoauto — сжимать gzip на источнике, а если gzip там нет, делать дамп без сжатия (передача идёт с rsync -z, в .sql.gz дамп упаковывается на приёмнике). yes — требовать gzip на источнике, no — не сжимать на источнике
REMOTE_TMP_DIR/tmpКуда на источнике класть временный дамп

Файлы и хранилище

ПараметрПо умолчаниюОписание
REMOTE_SITE_DIR— (обязательно)Каталог сайта на источнике, абсолютный путь, без пробелов
LOCAL_SITE_DIR— (обязательно)Куда копировать у себя, абсолютный путь
RSYNC_DELETEnoyes — удалять локально файлы, которых нет на источнике
RSYNC_EXCLUDESпустоМассив исключений: ('cache/' '*.log')
RSYNC_OPTS-azБазовые опции rsync
RSYNC_TIMEOUT600Таймаут ввода-вывода rsync, сек
RETRY_COUNT / RETRY_DELAY3 / 30Число попыток и пауза (сек) при сбоях rsync
LOCAL_BACKUP_DIR— (обязательно при DB_DUMP=yes)Каталог для дампов; не должен совпадать с LOCAL_SITE_DIR
KEEP_DUMPS7Сколько последних дампов хранить (0 — все)
LOG_FILEпустоЕсли задан — весь вывод в файл, ошибки дублируются в stderr

Развёртывание дампа (опционально)

ПараметрПо умолчаниюОписание
RESTOREnoyes — залить скачанный дамп в локальную БД
LOCAL_DB_TYPEкак REMOTE_DB_TYPEmysql / pgsql
LOCAL_DB_HOST / LOCAL_DB_PORTlocalhost / 3306 или 5432Адрес локальной БД
LOCAL_DB_NAMEкак REMOTE_DB_NAMEЦелевая БД
LOCAL_DB_USER, LOCAL_DB_PASS— (user обязателен при RESTORE)Доступ к локальной БД
LOCAL_DB_RECREATEnoyes — перед заливкой удалить и создать БД (mysql) / схему public (pgsql). При no таблицы из дампа перезаписываются, лишние остаются
LOCAL_CLIENT_BINmysql / psqlНапример mariadb
LOCAL_RESTORE_OPTSпустоДоп. опции клиента
ALLOW_RESTORE_TO_SOURCEnoСнимает защиту от заливки в БД самого источника

Аутентификация по ssh

SSH_AUTHКак работаетЧто нужно
keyssh-ключ (SSH_KEY), без паролей. Рекомендуется для cron.Ничего дополнительного
plainПароль прямо в конфиге (SSH_PASS). Передаётся ssh через SSH_ASKPASS-помощник (временный файл с правами 700, удаляется при выходе). Пароля нет в аргументах процессов.Ничего дополнительного
sshpassПароль из отдельного файла SSH_PASS_FILE (chmod 600).Пакет sshpass
Пароль в открытом виде в конфиге — компромисс. Если можно, используйте ключ. Для plain и sshpass обязательно chmod 600 на конфиг/файл пароля (скрипт предупредит о слишком широких правах).

Настройка ключа

ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ''
ssh-copy-id -i /root/.ssh/id_ed25519.pub -p 22 deploy@example.com

Cron

# каждые 30 минут
*/30 * * * * /opt/site_sync/site_sync.sh /etc/site_sync.conf

# раз в сутки в 03:15
15 3 * * * /opt/site_sync/site_sync.sh /etc/site_sync.conf

Скрипт сам добавляет стандартные каталоги в PATH (в cron он обычно урезан). Если задан LOG_FILE, весь обычный вывод идёт в файл, а ошибки дополнительно уходят в stderr — cron пришлёт письмо (если настроен MAILTO). Одновременный запуск двух экземпляров блокируется.

Защита и поведение

Коды возврата

КодЗначение
0Успех
1Ошибка выполнения (ssh, дамп, rsync, развёртывание)
2Ошибка конфига или аргументов
3Уже запущен другой экземпляр

Если что-то не так