Автобэкапы по расписанию (cron)
Ручной запуск бэкапа рано или поздно забывается — а cron умеет делать это без вас: сам запускает скрипт rsync или restic по расписанию, каждую ночь, без вашего участия. В этой статье — как поставить такой скрипт на расписание через crontab, не потерять его логи и не запутаться в часовых поясах.
Что понадобится
- Linux VPS mHost — подходит любой из дистрибутивов: Ubuntu 22.04/24.04, Debian 11/12, AlmaLinux/Rocky Linux 8/9.
- Доступ по SSH под
rootили пользователем сsudo. - Рабочий скрипт или команда бэкапа на основе rsync или restic, которую вы уже проверили вручную. Если такого скрипта ещё нет — сначала настройте сам инструмент по статьям «Бэкапы через rsync» или «Бэкапы через restic»; эта статья — только про расписание и автозапуск, не про сам rsync/restic.
- Место назначения для бэкапов: отдельный диск/примонтированный том на этом же сервере либо удалённый хост — в зависимости от того, что вы выбрали в статьях выше.
Шаг 1. Подготовьте скрипт бэкапа
cron умеет запускать что угодно — команду, скрипт, целую программу, — но длинную команду удобнее не писать прямо в crontab, а оформить отдельным исполняемым файлом. Так его проще редактировать, тестировать вручную и переиспользовать.
Ниже — два минимальных примера. Возьмите вариант, который соответствует вашему инструменту (подробности — по ссылкам из раздела выше), и сохраните как /usr/local/bin/backup.sh.
Скрипт на основе rsync
sudo nano /usr/local/bin/backup.sh#!/bin/sh
set -e
SRC="/var/www"
DEST="/mnt/backup/www"
rsync -a --delete "$SRC" "$DEST"-a (--archive) — рекурсивно скопировать каталог, сохранив права, время изменения, символьные ссылки и владельца; --delete — удалить в DEST файлы, которых уже нет в SRC, чтобы копия оставалась зеркалом, а не только росла. DEST может быть и удалённым хостом по SSH (user@host:/path, с флагом -e ssh) — про это и про остальные флаги rsync см. статью «Бэкапы через rsync».
Скрипт на основе restic
Репозиторий restic создаётся один раз, вручную, заранее. Сначала заведите файл с паролем репозитория:
sudo mkdir -p /etc/restic
sudo nano /etc/restic/password
sudo chmod 600 /etc/restic/passwordВпишите в файл /etc/restic/password один длинный пароль (без переноса строки в конце) и сохраните — это пароль шифрования репозитория, а не пароль пользователя ОС. Затем инициализируйте репозиторий:
sudo restic --repo /mnt/backup/restic-repo --password-file /etc/restic/password initТот же путь к репозиторию и тот же файл пароля идут первыми строками и в самом скрипте — уже как переменные окружения RESTIC_REPOSITORY и RESTIC_PASSWORD_FILE. Тогда restic не будет спрашивать их интерактивно при запуске из cron, где спросить их попросту не у кого:
sudo nano /usr/local/bin/backup.sh#!/bin/sh
set -e
export RESTIC_REPOSITORY="/mnt/backup/restic-repo"
export RESTIC_PASSWORD_FILE="/etc/restic/password"
restic backup /var/www
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prunerestic backup создаёт новый снимок; restic forget с флагами --keep-daily/--keep-weekly/--keep-monthly удаляет старые снимки по политике хранения, а --prune сразу освобождает место, занятое уже неиспользуемыми данными. /mnt/backup/restic-repo может быть не только локальным путём, но и SFTP- или S3-совместимым хранилищем — про выбор backend'а, восстановление из копии и тонкую настройку retention см. статью «Бэкапы через restic».
Сделайте скрипт исполняемым и один раз запустите его руками — прежде чем доверять его cron, убедитесь, что он вообще отрабатывает:
sudo chmod +x /usr/local/bin/backup.sh
sudo /usr/local/bin/backup.shШаг 2. Откройте crontab
У каждого пользователя свой отдельный crontab. Команда crontab -e открывает crontab текущего пользователя; чтобы отредактировать crontab root (обычно то, что нужно для системного бэкап-скрипта вроде /var/www), выполните:
sudo crontab -eПолезные соседние команды:
crontab -l— показать текущий crontab, ничего не редактируя.crontab -r— удалить весь crontab пользователя целиком, без подтверждения.
Перед тем как добавлять задачу, убедитесь, что сам cron установлен и запущен:
# Ubuntu / Debian
systemctl status cron
# AlmaLinux / Rocky Linux
systemctl status crondЕсли служба не найдена — установите пакет и включите автозапуск:
# Ubuntu / Debian
sudo apt install -y cron
sudo systemctl enable --now cron
# AlmaLinux / Rocky Linux
sudo dnf install -y cronie
sudo systemctl enable --now crondШаг 3. Синтаксис расписания cron
Каждая строка crontab описывает расписание пятью полями, а дальше идёт сама команда. Порядок полей: минута · час · день месяца · месяц · день недели.
- минута — 0–59
- час — 0–23
- день месяца — 1–31
- месяц — 1–12
- день недели — 0–7 (0 и 7 — воскресенье)
*— «любое значение», всё поле целиком.,— список значений:1,15— 1-го и 15-го числа.-— диапазон:8-11в поле часа — с 8 до 11 включительно./— шаг:*/2в поле часа — каждый второй час (0, 2, 4, …).
Примеры:
0 3 * * *— Каждую ночь в 03:0030 2 * * 0— Каждое воскресенье в 02:300 */6 * * *— Каждые 6 часов (00:00, 06:00, 12:00, 18:00)0 3 1 * *— 1-го числа каждого месяца в 03:00
Вместо пяти полей можно использовать короткие «имена»: @daily (эквивалент 0 0 * * *), @weekly (0 0 * * 0), @monthly, @hourly, @reboot (один раз при старте системы) и другие. Для ночного бэкапа удобнее явные пять полей — так вы точно контролируете час: @daily сработает в полночь, а не, скажем, в 03:00, когда нагрузка на диск обычно ниже.
Шаг 4. Добавьте ночную задачу и перенаправьте логи
Откройте crontab root и добавьте строку:
sudo crontab -e0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&10 3 * * *— каждую ночь в 03:00 (о том, по какому часовому поясу, — в шаге 5 ниже).>> /var/log/backup.log— дописывать стандартный вывод скрипта в конец файла (>вместо>>каждый раз перезаписывал бы лог с нуля).2>&1— направить туда же и поток ошибок (stderr); порядок важен: сначала>>перенаправляетstdoutв файл, и только потом2>&1говорит «поток 2 — туда же, куда сейчас смотрит поток 1».
0 3 * * * /usr/bin/flock -n /var/run/backup.lock /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1Флаг -n — не ждать, а сразу выйти, если предыдущий запуск ещё не закончился.
Файл /var/log/backup.log будет расти бесконечно, если его не ротировать, — при необходимости заведите для него отдельное правило logrotate (отдельная тема, здесь не рассматривается).
Сохраните файл и проверьте, что задача добавилась:
sudo crontab -lШаг 5. Часовой пояс
cron ориентируется на системные дату и время сервера — а не на часовой пояс, который вы держали в уме, когда писали 0 3 * * *. Проверьте текущий часовой пояс сервера:
timedatectlПри необходимости смените его (например, на московское время):
sudo timedatectl set-timezone Europe/MoscowСписок всех доступных зон — timedatectl list-timezones.
Шаг 6. Проверьте, что бэкап действительно отработал
Дайте задаче сработать хотя бы раз (не обязательно ждать ночи — можно временно поставить время на пару минут вперёд, проверить результат, а затем вернуть 0 3 * * * обратно) и посмотрите лог скрипта:
tail -n 50 /var/log/backup.logЗаодно проверьте, что сам cron видел и запускал задачу, — это отдельная запись, не совпадающая с выводом вашего скрипта:
# Ubuntu / Debian
journalctl -u cron --since today
grep CRON /var/log/syslog
# AlmaLinux / Rocky Linux
journalctl -u crond --since today
sudo tail -n 50 /var/log/cronНаконец, убедитесь, что в месте назначения действительно появились свежие данные — новый файл/каталог с сегодняшней датой для rsync или новый снимок для restic (restic snapshots).
Что дальше
Детали самого инструмента — установку, выбор места хранения, восстановление из копии, тонкую настройку retention — смотрите в статьях «Бэкапы через rsync» и «Бэкапы через restic».