Serwer zarabia na siebie, pracując, gdy śpisz: kopie zapasowe, rotacja logów, odnawianie certyfikatów, raport na dziewiątą. Linux ma do tego dwa harmonogramy. Cron ma czterdzieści lat i mieści się w jednej linii. Timery systemd to dwa małe pliki, za to logi, nadrabianie po przestoju i dokładny czas. Ten poradnik omawia oba na Ubuntu 24.04; każde zachowanie sprawdziliśmy na świeżym serwerze z naszego obrazu, łącznie z trzema błędami, przez które zadanie cron pada bez słowa.
Potrzebujesz użytkownika z sudo; poradnik konfiguracji Ubuntu go tworzy.
1. Cron w pięć minut
Cron jest zainstalowany i działa na naszych obrazach Ubuntu i Debian. Każdy użytkownik ma własną tabelę zadań; swoją edytujesz tak:
crontab -e
Każda linia to pięć pól czasu i polecenie:
# 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
Czyli: o 03:30 każdej nocy, co 5 minut, o 09:00 w dni robocze i raz po każdym uruchomieniu. */5 to co piąta wartość, 1-5 zakres, 1,15 lista. Obowiązuje strefa serwera, na naszych obrazach UTC; ustaw swoją raz według poradnika o nazwie hosta i strefie czasowej, a cron będzie jej używał.
Co się uruchomiło, sprawdzisz w journalctl -u cron. Każde uruchomienie zapisuje użytkownika i polecenie, i właśnie tam widać trzy pułapki.
Pułapka 1: wyjście znika. Cron wysyła wyjście zadania pocztą do użytkownika. Nasz obraz nie ma serwera pocztowego, więc w dzienniku pojawiło się (CRON) info (No MTA installed, discarding output), a wyjście przepadło. Przekieruj je sam, jak w pierwszym przykładzie: >> /var/log/backup.log 2>&1.
Pułapka 2: znak procentu. W crontab % kończy polecenie, a resztę zamienia na standardowe wejście. Zaplanowaliśmy date +%F > /tmp/today. Dziennik pokazuje, co cron naprawdę uruchomił: CMD (date +). Plik nie powstał i żaden błąd do nas nie dotarł. Pisz \% albo przenieś polecenie do skryptu i planuj skrypt.
Pułapka 3: inne środowisko. Cron uruchamia zadania przez /bin/sh, nie bash, w katalogu domowym i z okrojonym środowiskiem. Na Ubuntu 24.04 PATH okazał się lepszy od swojej reputacji — pełna ścieżka systemowa, z /usr/local/bin i /snap/bin, zarówno dla root, jak i zwykłego użytkownika. Wciąż brakuje wszystkiego z katalogu domowego: ~/.local/bin, node z nvm, pipx, cargo. Podawaj w zadaniu pełne ścieżki albo zaczynaj linię od . $HOME/.profile;.
Zadania należące do systemu, a nie użytkownika, umieszczaj w /etc/cron.d/ jako osobny plik z jednym dodatkowym polem — użytkownikiem:
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Ubuntu uruchamia też wszystko z /etc/cron.hourly, cron.daily, cron.weekly i cron.monthly — w 17. minucie każdej godziny, o 06:25, o 06:47 w niedziele i o 06:52 pierwszego dnia miesiąca. Wrzuć tam wykonywalny skrypt, a uruchomi się razem z resztą.
2. Timery systemd
Timer to dwie jednostki: usługa, która wykonuje pracę, i timer, który mówi kiedy. Najpierw utwórz skrypt, potem jednostki.
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
Włączaj timer, nie usługę:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
list-timers pokazuje następne uruchomienie, ile do niego zostało, i ostatnie uruchomienie. Logów nie trzeba konfigurować: w journalctl -u backup.service jest każdy start, koniec i każda linia wyjścia ze znacznikami czasu. Aby uruchomić zadanie od razu — sudo systemctl start backup.service; tak samo warto przetestować skrypt, zanim zaufasz harmonogramowi.
Składnia kalendarza. OnCalendar czyta się jako dzieńtygodnia rok-miesiąc-dzień godzina:minuta:sekunda, * to dowolna wartość. Sprawdź wyrażenie przed użyciem:
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
Polecenie wypisuje postać znormalizowaną i najbliższe daty. Kilka wyrażeń, które sprawdziliśmy:
| OnCalendar | Znaczenie |
|---|---|
*-*-* 03:30 | Codziennie o 03:30 |
Mon..Fri *-*-* 09:00 | W dni robocze o 09:00 |
*:0/15 | Co 15 minut |
weekly | W poniedziałki o 00:00 |
*-*-01 04:00 | Pierwszego dnia każdego miesiąca o 04:00 |
*-*-* 03:00 Europe/Kyiv | 03:00 czasu kijowskiego; u nas uruchomił się o 01:00 UTC |
Trzy ustawienia, które warto znać. Persistent=true zapisuje ostatnie uruchomienie na dysku i nadrabia uruchomienie pominięte, gdy serwer był wyłączony lub timer zatrzymany. Zatrzymaliśmy nasz timer „co dwie minuty”, poczekaliśmy, aż minie planowe uruchomienie, i włączyliśmy go ponownie: pominięte uruchomienie ruszyło w tej samej sekundzie. Bez Persistent timer po prostu czeka na kolejny termin.
AccuracySec to największa niespodzianka. Domyślnie systemd grupuje timery w oknie jednej minuty, żeby rzadziej budzić system, dlatego nasze pierwsze uruchomienie przyszło o 07:42:18, a nie o 07:42:00. Z AccuracySec=1s kolejne wypadły co do sekundy o 07:46:00 i 07:48:00. Ustaw je, gdy liczy się minuta; dla nocnej kopii zostaw domyślne.
RandomizedDelaySec=10m robi odwrotnie i to celowo: rozkłada start w oknie, żeby dziesięć serwerów nie uderzyło w ten sam magazyn kopii w tej samej sekundzie.
Do jednorazowego zadania pliki w ogóle nie są potrzebne:
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
Polecenie tworzy tymczasowy timer, który zadziała raz i zniknie; do tego czasu widać go w systemctl list-timers.
3. Co wybrać
| Cron | Timer systemd | |
|---|---|---|
| Konfiguracja | 1 linia | 2 pliki |
| Logi | Tylko po przekierowaniu wyjścia | journalctl -u name.service |
| Pominięte uruchomienie, gdy serwer był wyłączony | Przepada | Wykona się przy starcie z Persistent=true |
| Zadanie jeszcze działa przy kolejnym terminie | Startuje druga kopia | Pomijane, dopóki pierwsze nie skończy |
| Dokładny czas | Co do minuty | Co do sekundy z AccuracySec=1s |
| Status | Brak | list-timers, systemctl status |
Wybierz cron dla szybkiej linii, którą rozpoznasz i za rok. Wybierz timer dla wszystkiego, czego awarię musisz zobaczyć, co nie może się nakładać albo co musi się wykonać mimo pominięcia przez restart: kopie zapasowe, odnawianie certyfikatów, sprzątanie baz danych. Jeśli zadanie cron może się nałożyć, owiń je: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, a druga kopia od razu się zakończy.
Oba harmonogramy uruchamiają zadanie i się zatrzymują. Dla programu, który ma działać całą dobę i wstawać po awarii, potrzebna jest usługa, a nie harmonogram; zobacz, jak utworzyć usługę systemd, a dla Windows — jak uruchomić skrypt 24/7 na Windows Server. Dobry pierwszy timer pochodzi z naszego poradnika kopii zapasowych z restic; automatyczne aktualizacje bezpieczeństwa to timer, który Ubuntu już dostarcza, apt-daily-upgrade.timer, jeden z 17 działających na świeżym serwerze.
Komentarze
Brak komentarzy. Bądź pierwszy.