cron — zakazivanje poslova na Linuxu

cron je servis koji pokreće komande po rasporedu — svakog minuta, svake noći u tri, svakog prvog u mesecu. Sve što bi inače morao da radiš ručno svakog dana može da radi sam: backup baze, brisanje starih fajlova, provera da li servis radi, slanje izveštaja.

Posao koji cron pokreće zove se cron job, a raspored se upisuje u tabelu koja se zove crontab.

Uređivanje sopstvenog crontab-a

$ crontab -e

Otvara tvoj lični crontab u podrazumevanom editoru. Ako te dočeka vi a ti to ne želiš:

$ export EDITOR=nano
$ crontab -e

Pregled bez uređivanja:

$ crontab -l

Brisanje celog crontab-a — bez pitanja, bez povratka:

$ crontab -r

Tastature -r i -e su jedna do druge. Naviknuti se na crontab -l pre svega ostalog je jeftina navika koja te jednog dana spasi.

Tuđi crontab, kao administrator:

# crontab -u nginx -l

Sintaksa

Svaki red ima pet vremenskih polja i komandu:

*  *  *  *  *  komanda
│  │  │  │  │
│  │  │  │  └─ dan u nedelji (0-7, gde su 0 i 7 nedelja)
│  │  │  └──── mesec (1-12)
│  │  └─────── dan u mesecu (1-31)
│  └────────── sat (0-23)
└───────────── minut (0-59)

Zvezdica znači „svaki". Redosled polja ide od najmanje jedinice ka najvećoj, osim dana u nedelji koji je na kraju.

Operatori

ZapisZnačenje
*svaka vrednost
5tačno ta vrednost
1,15,30nabrajanje
1-5opseg
*/10svakih 10 jedinica
9-17/2na svaka 2, u opsegu 9-17

Primeri

*/5 * * * *      svakih 5 minuta
0 * * * *        svakog punog sata
30 2 * * *       svakog dana u 2:30
0 3 * * 0        nedeljom u 3:00
0 0 1 * *        prvog u mesecu u ponoć
0 9-17 * * 1-5   svakog punog sata od 9 do 17, radnim danima
15 4 1,15 * *    u 4:15, prvog i petnaestog u mesecu

Pun red izgleda ovako:

30 2 * * * /home/alen/skripte/backup.sh

Zamka: dan u mesecu i dan u nedelji

Ako su oba polja zadata (nijedno nije *), cron pokreće posao kada je zadovoljeno bilo koje od njih — ne oba. Ovaj red se izvršava petnaestog u mesecu i svakog ponedeljka:

0 3 15 * 1

Ako ti treba samo petnaesti, ostavi dan u nedelji kao zvezdicu.

Skraćenice

@reboot     pri svakom pokretanju sistema
@hourly     isto što i  0 * * * *
@daily      isto što i  0 0 * * *
@weekly     isto što i  0 0 * * 0
@monthly    isto što i  0 0 1 * *
@yearly     isto što i  0 0 1 1 *
@daily /usr/local/bin/ocisti-temp.sh
@reboot /home/alen/skripte/start-tunel.sh

Sistemski cron

Pored korisničkih crontab-ova postoji i sistemski, koji ima jedno polje više — korisnika pod kojim se posao izvršava.

Glavni fajl je /etc/crontab, ali njega ne diraj. Umesto toga napravi svoj fajl u /etc/cron.d/:

# vi /etc/cron.d/backup-baze
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

30 2 * * *  root  /opt/skripte/backup-baze.sh

Prednost je što je svaki posao u svom fajlu — lako se vidi šta radi, lako se ukloni, i lako se raspoređuje kroz alat za automatizaciju.

Postoje i gotovi direktorijumi za jednostavne slučajeve. Sve izvršne skripte u njima pokreću se u zadatom ritmu, bez ikakve sintakse:

/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/

Skripta tu mora imati izvršnu dozvolu i — pažnja — ne sme imati ekstenziju .sh na sistemima koji koriste run-parts. Fajl sa tačkom u imenu biva preskočen bez ijedne poruke o grešci.

Anacron

cron podrazumeva da sistem radi non-stop. Ako je server bio ugašen u 3:00, taj posao je jednostavno propušten i neće se nadoknaditi.

anacron rešava upravo to — pamti kada je posao poslednji put izvršen i pokreće ga čim sistem ponovo radi. Konfiguracija je u /etc/anacrontab:

# period  kašnjenje  identifikator      komanda
1         5          cron.daily         run-parts /etc/cron.daily
7         25         cron.weekly        run-parts /etc/cron.weekly

Prvi broj je period u danima, drugi je koliko minuta da sačeka posle pokretanja sistema. Ovo je bitno na laptopovima i serverima koji se gase — na serveru koji radi 24/7 obični cron je dovoljan.

Zašto skripta radi ručno, a ne radi iz crona

Ovo je najčešći problem sa cron-om i skoro uvek ima isti uzrok.

1. PATH je drugačiji

cron pokreće posao sa vrlo skromnim okruženjem — najčešće samo /usr/bin:/bin. Tvoje podešavanje iz .bashrc ne postoji, jer to nije interaktivna sesija.

Rešenje: uvek piši pune putanje.

# ne radi
0 2 * * * mysqldump baza > /backup/baza.sql

# radi
0 2 * * * /usr/bin/mysqldump baza > /backup/baza.sql

Punu putanju do komande daje which:

$ which mysqldump
/usr/bin/mysqldump

Alternativa je da PATH postaviš na vrhu crontab-a:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

2. Znak procenta

U crontab-u % ima posebno značenje i mora se zaštititi obrnutom kosom crtom. Ovo je česta zamka kod datuma:

# ne radi
0 2 * * * /opt/backup.sh > /var/log/backup-$(date +%Y%m%d).log

# radi
0 2 * * * /opt/backup.sh > /var/log/backup-$(date +\%Y\%m\%d).log

3. Nedostaje izvršna dozvola

$ chmod +x /opt/skripte/backup.sh

4. Radni direktorijum nije onaj koji misliš

cron startuje posao iz korisnikovog home direktorijuma. Relativne putanje u skripti neće raditi kako očekuješ — koristi apsolutne, ili na početak skripte stavi cd u pravi direktorijum.

5. Nedostaje prazan red na kraju

Neke implementacije crona ignorišu poslednji red ako fajl ne završava prelomom reda. crontab -e to obično sredi sam, ali ako fajl pišeš direktno u /etc/cron.d/, ostavi prazan red na kraju.

Kako se cron debaguje

Prvo pogledaj da li je posao uopšte pokrenut:

# journalctl -u crond --since today

(Na Debianu i Ubuntuu servis se zove cron, ne crond.) U ispisu vidiš svaki pokušaj izvršenja — ali ne i grešku same skripte. Za to preusmeri izlaz u fajl:

0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1

Zapis 2>&1 šalje i greške u isti fajl. Bez toga vidiš samo normalan izlaz, a greška — koja te jedina zanima — nestaje. Više o tome u lekciji o pipingu i redirekciji.

Ako te ne zanima log ali hoćeš tišinu:

0 2 * * * /opt/backup.sh > /dev/null 2>&1

Najbrži test rasporeda: zakaži posao za dva minuta unapred sa */1 * * * *, proveri da radi, pa tek onda postavi pravo vreme. Čekanje do sutra u 3:00 da bi otkrio grešku u kucanju nije plan.

Provera da servis radi

# systemctl status crond
# systemctl enable --now crond

Zvuči trivijalno, ali na minimalnim instalacijama i u kontejnerima cron često nije ni instaliran ni pokrenut.

Ko sme da koristi cron

Pristup se kontroliše kroz dva fajla:

  • /etc/cron.allow — ako postoji, samo korisnici sa spiska
  • /etc/cron.deny — svi osim onih sa spiska

Ako postoji cron.allow, cron.deny se ignoriše.

cron ili systemd timer?

systemd ima svoj mehanizam za zakazivanje — timer jedinice — koji nudi bolje logovanje, zavisnosti između poslova i nadoknađivanje propuštenih izvršenja.

U praksi: cron je i dalje svuda, kraći je i svaki administrator ga zna. Za jednostavne poslove nema razloga da ga menjaš. Ako ti treba da se posao pokrene tek pošto se digne baza, ili hoćeš da svaki posao ima uredan zapis u journal-u, timer je bolji izbor.


Povezano: systemctl · journalctl · Pisanje skriptova · Administracija i servisi

Comments

Popular posts from this blog

Početak u Linuxu — šta je i zašto se uči

Konverzija tipova podataka u Pythonu

groupadd