Сервер окупається тим, що працює, поки ви спите: бекапи, ротація логів, продовження сертифікатів, звіт до дев'ятої ранку. У Linux для цього є два планувальники. Cron — сорок років і один рядок. Таймери systemd — два невеликі файли, зате логи, наздоганяння після простою й точний час. Цей посібник розбирає обидва на Ubuntu 24.04; кожну поведінку перевірено на свіжому сервері з нашого образу, зокрема три помилки, через які завдання cron падає без жодного слова.
Потрібен користувач із sudo; посібник з налаштування Ubuntu його створює.
1. Cron за п'ять хвилин
Cron встановлений і працює на наших образах Ubuntu та Debian. У кожного користувача своя таблиця завдань; редагуйте свою так:
crontab -e
Кожен рядок — п'ять полів часу й команда:
# min hour day month weekday command
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/local/bin/check.sh
0 9 * * 1-5 /usr/local/bin/report.sh
@reboot /usr/local/bin/start-tunnel.sh
Тобто: о 03:30 щоночі, кожні 5 хвилин, о 09:00 у будні й один раз після кожного завантаження. */5 — кожне п'яте значення, 1-5 — діапазон, 1,15 — список. Час — за поясом сервера, на наших образах це UTC; задайте свій один раз за посібником про ім'я хоста й часовий пояс, і cron його використовуватиме.
Що запускалося, дивіться в journalctl -u cron. Кожен запуск записує користувача й команду, і саме там видно три пастки.
Пастка 1: вивід зникає. Cron надсилає вивід завдання користувачу поштою. У нашому образі немає поштового сервера, тож у журналі з'явилося (CRON) info (No MTA installed, discarding output), і вивід зник. Перенаправляйте його самі, як у першому прикладі: >> /var/log/backup.log 2>&1.
Пастка 2: знак відсотка. У crontab % завершує команду й перетворює решту на стандартне введення. Ми запланували date +%F > /tmp/today. Журнал показує, що cron запустив насправді: CMD (date +). Файл не з'явився, і жодна помилка до нас не дійшла. Пишіть \% або винесіть команду в скрипт і плануйте скрипт.
Пастка 3: інше оточення. Cron запускає завдання через /bin/sh, а не bash, у домашньому каталозі й з коротким оточенням. На Ubuntu 24.04 PATH виявився кращим за свою репутацію — повний системний шлях, включно з /usr/local/bin і /snap/bin, і для root, і для звичайного користувача. Чого досі немає, то це всього з домашнього каталогу: ~/.local/bin, node з nvm, pipx, cargo. Пишіть у завданні повні шляхи або починайте рядок з . $HOME/.profile;.
Завдання, що належать системі, а не користувачу, кладіть у /etc/cron.d/ окремим файлом з одним додатковим полем — користувачем:
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Ще Ubuntu запускає все з /etc/cron.hourly, cron.daily, cron.weekly і cron.monthly — о 17-й хвилині кожної години, о 06:25, о 06:47 у неділю й о 06:52 першого числа. Покладіть туди виконуваний скрипт, і він запускатиметься разом з іншими.
2. Таймери systemd
Таймер — це два юніти: служба, яка виконує роботу, і таймер, який каже коли. Спершу створіть скрипт, потім юніти.
sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30
[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
Вмикайте таймер, а не службу:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
list-timers показує наступний запуск, скільки до нього лишилося, і останній запуск. Логи не треба налаштовувати: у journalctl -u backup.service є кожен старт, завершення й кожен рядок виводу з позначками часу. Щоб виконати завдання просто зараз — sudo systemctl start backup.service; так само варто перевірити скрипт, перш ніж довіряти розкладу.
Синтаксис календаря. OnCalendar читається як деньтижня рік-місяць-день година:хвилина:секунда, * — будь-яке значення. Перевірте вираз до використання:
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
Команда друкує нормалізовану форму й найближчі дати. Кілька виразів, які ми перевірили:
| OnCalendar | Значення |
|---|---|
*-*-* 03:30 | Щодня о 03:30 |
Mon..Fri *-*-* 09:00 | У будні о 09:00 |
*:0/15 | Кожні 15 хвилин |
weekly | Щопонеділка о 00:00 |
*-*-01 04:00 | Першого числа кожного місяця о 04:00 |
*-*-* 03:00 Europe/Kyiv | 03:00 за Києвом; у нас спрацював о 01:00 UTC |
Три налаштування, які варто знати. Persistent=true записує останній запуск на диск і наздоганяє запуск, пропущений, поки сервер був вимкнений або таймер зупинений. Ми зупинили наш таймер «кожні дві хвилини», дочекалися, поки мине плановий запуск, і ввімкнули його знову: пропущений запуск спрацював у ту ж секунду. Без Persistent таймер просто чекає наступного слоту.
AccuracySec — головний сюрприз. Типово systemd збирає таймери у вікні в одну хвилину, щоб рідше будити систему, тому наш перший запуск прийшов о 07:42:18, а не о 07:42:00. З AccuracySec=1s наступні запуски припали рівно на 07:46:00 і 07:48:00, до секунди. Задайте його, коли важлива хвилина; для нічного бекапу лишіть типове значення.
RandomizedDelaySec=10m робить протилежне й навмисно: розмазує старт по вікну, щоб десять серверів не вдарили по одному сховищу бекапів в ту саму секунду.
Для разового завдання файли взагалі не потрібні:
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
Команда створює тимчасовий таймер, який спрацює один раз і зникне; до того його видно в systemctl list-timers.
3. Що обрати
| Cron | Таймер systemd | |
|---|---|---|
| Налаштування | 1 рядок | 2 файли |
| Логи | Лише якщо перенаправити вивід | journalctl -u name.service |
| Пропущений запуск, поки сервер був вимкнений | Втрачено | Виконається під час завантаження з Persistent=true |
| Завдання ще працює до наступного тіку | Запускається друга копія | Пропускається, поки не завершиться перша |
| Точний час | До хвилини | До секунди з AccuracySec=1s |
| Статус | Немає | list-timers, systemctl status |
Беріть cron для швидкого рядка, який ви впізнаєте і через рік. Беріть таймер для всього, де треба бачити збій, де запуски не мають перекриватися або де пропущений через перезавантаження запуск усе одно має виконатися: бекапи, продовження сертифікатів, очищення баз даних. Якщо завдання cron може перекритися, обгорніть його: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, і друга копія одразу завершиться.
Обидва планувальники запускають завдання й зупиняються. Для програми, яка має працювати цілодобово й підніматися після падіння, потрібна служба, а не розклад; дивіться, як створити службу systemd, а для Windows — як запустити скрипт 24/7 на Windows Server. Добрий перший таймер — з нашого посібника з бекапу через restic; автоматичні оновлення безпеки — це таймер, який Ubuntu вже постачає, apt-daily-upgrade.timer, один із 17, що працюють на свіжому сервері.
Коментарі
Поки немає коментарів. Будьте першим.