Сървърът си изкарва хляба, като работи, докато спиш: бекъпи, ротация на логове, подновяване на сертификати, отчет в девет. В 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-те, работещи на нов сървър.
Коментари
Още няма коментари. Бъди първият.