Скрипт резервной копии готов: вы запускаете его руками, он отрабатывает, архив появляется. Теперь хочется, чтобы он запускался сам каждую ночь в 03:00, а вы утром только проверяли, что всё прошло. На Ubuntu для этого есть два способа, cron и таймеры systemd. Разберём оба на этом же скрипте /home/user/backup.sh.
Как поставить задачу в cron
Cron это служба, которая запускает команды по расписанию. В Ubuntu 24.04 она уже установлена и работает, так что ставить ничего не нужно. Убедиться можно так:
systemctl status cron
В ответе ищите строку active (running): она значит, что служба запущена.
Задачи хранятся в личной таблице пользователя, она называется crontab. Открыть её и посмотреть содержимое:
crontab -e
crontab -l
crontab -e открывает таблицу в редакторе. При первом запуске система спросит, какой редактор взять, и nano вполне подойдёт. crontab -l просто выводит задачи, ничего не меняя. Таблица у каждого пользователя своя, поэтому задачи root и вашего обычного пользователя не смешиваются.
Что значат пять звёздочек
Строка crontab состоит из пяти полей времени и команды:
┌ минута (0-59)
│ ┌ час (0-23)
│ │ ┌ день месяца (1-31)
│ │ │ ┌ месяц (1-12)
│ │ │ │ ┌ день недели (0-7, 0 и 7 это воскресенье)
│ │ │ │ │
* * * * * команда
Звёздочка значит «любое значение». Наша ночная копия выглядит так: 0 3 * * *, то есть нулевая минута третьего часа, любой день. Вот ещё несколько расписаний, которые встречаются чаще всего:
*/5 * * * * /home/user/check.sh
0 3 * * * /home/user/backup.sh
30 9 * * 1 /home/user/report.sh
0 0 1 * * /home/user/monthly.sh
@reboot /home/user/start.sh
Сверху вниз: каждые 5 минут, каждый день в 03:00, по понедельникам в 09:30, первого числа в полночь и один раз при запуске сервера. Значения можно перечислить через запятую (1,15) или задать диапазон через дефис: 1-5 в поле дня недели значит с понедельника по пятницу.
Одна ловушка: время считается по часовому поясу сервера, а он часто стоит UTC. Проверьте его командой timedatectl, иначе «03:00» наступит в 06:00 по Москве.
Задача сработала, но где посмотреть результат
Всё, что скрипт печатает, cron по умолчанию отправляет по локальной почте. Но на VPS почтовой программы обычно нет, и вывод просто пропадает. Так что дописывайте его в файл:
0 3 * * * /home/user/backup.sh >> /home/user/backup.log 2>&1
>> дописывает обычный вывод в backup.log, а 2>&1 отправляет туда же ошибки. Без этой второй части вы увидите, что копия прошла, но не увидите, почему она упала. Если вывод не нужен совсем, вместо файла поставьте /dev/null.
Сам факт запуска cron записывает в журнал systemd:
journalctl -u cron --since today
В строках CMD видно, когда, от какого пользователя и какая команда запустилась. Но сам вывод команды туда не попадает, поэтому файл из примера выше всё равно нужен. Подробнее о журналах: журналы и службы systemd.
В терминале работает, а в cron нет. Почему
Это самая частая жалоба, и причина почти всегда одна: cron запускает команды в урезанном окружении. Он не читает ваши .bashrc и .profile, а команды выполняет через /bin/sh, а не через bash. В Ubuntu 24.04 cron берёт PATH из /etc/environment, там есть системные каталоги вроде /usr/bin и /usr/local/bin. Зато всё, что вы добавляли в PATH сами, cron не видит: виртуальное окружение Python, ~/.local/bin, Node.js из nvm.
Поэтому в команде пишите полные пути: /usr/bin/python3 /home/user/bot/run.py, а не python3 run.py. Где лежит программа, подскажет which python3.
Другой путь: задать переменные в начале crontab, тогда они действуют на все строки ниже:
SHELL=/bin/bash
PATH=/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin
MAILTO=""
SHELL выбирает оболочку, PATH перечисляет каталоги, где искать программы, а MAILTO="" отключает письма. Каталог ~/.local/bin здесь записан полностью, потому что знак ~ cron в этой строке не раскрывает.
Ещё три мелочи, на которых спотыкаются:
- Текущий каталог у задачи не тот, что у вас в терминале. Пишите полные пути к файлам или начните команду с
cd /home/user/bot &&. - Скрипту нужна первая строка
#!/bin/bashи право на запуск:chmod +x /home/user/backup.sh. - Знак
%cron считает концом команды. Строкаdate +%F > file.txtвыполнится какdate +, и файл не появится. Перед процентом ставьте обратную косую:date +\%F.
Если задача молчит, первым делом проверьте пути и знак %: в большинстве случаев дело в них.
Как сделать то же самое таймером systemd
Таймер systemd устроен как пара файлов. Служба (.service) описывает, что запускать, а таймер (.timer) описывает, когда. Переведём на таймер нашу ночную копию.
Сначала служба:
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Резервная копия
[Service]
Type=oneshot
ExecStart=/home/user/backup.sh
User=user
Type=oneshot говорит systemd, что задача выполнится и завершится, а не будет работать постоянно. ExecStart указывает полный путь к скрипту, User задаёт, от чьего имени его запускать.
Теперь таймер:
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Ежедневный запуск резервной копии
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
OnCalendar задаёт то же расписание: каждый день в 03:00. А Persistent=true делает то, чего cron не умеет: если сервер в 03:00 был выключен, копия запустится сразу после включения. Имена файлов совпадают, backup.service и backup.timer, и по этому совпадению systemd понимает, какую службу запускать.
Остаётся включить таймер:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers
daemon-reload заставляет systemd прочитать новые файлы. enable --now включает таймер и сохраняет его после перезагрузки. Сама копия при этом не запустится сейчас, она дождётся 03:00. list-timers покажет, когда таймер сработал последний раз и когда сработает в следующий.
Расписание удобно проверить заранее: systemd-analyze calendar "Mon *-*-* 09:30" печатает ближайший момент срабатывания. Запустить копию вручную, не дожидаясь ночи, можно командой sudo systemctl start backup.service, а её вывод лежит в journalctl -u backup.service, без всяких перенаправлений в файл.
Так что выбрать
| Что важно | Cron | Таймер systemd |
|---|---|---|
| Настройка | одна строка | два файла |
| Вывод и ошибки | в файл вручную | сами в журнал |
| Сервер был выключен | запуск теряется | Persistent=true запустит после включения |
| Зависимости от других служб | нет | есть (After=, Requires=) |
| Окружение | урезанное | задаётся в файле службы |
Если задача короткая и потерять один запуск не страшно, берите cron: почистить папку, проверить сайт, обновить данные. Если задача важная, должна оставлять журнал или зависит от сети и базы, берите таймер. Резервную копию можно делать любым способом, общая схема есть в статье резервные копии VPS. А если по расписанию запускается бот на Python, пригодится статья сервер для Telegram-бота.
С чего начать
Поставьте ночную копию одной строкой в cron, с выводом в backup.log, и утром загляните в этот файл. Если там пусто или ошибка, вернитесь к разделу про окружение: скорее всего, не хватает полного пути. Нужен сервер под такие задачи: на странице подбора VPS в базе 262 тарифов от 140 ₽ в месяц, цены сверены 20 октября 2026 года.
