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
| Zapis | Značenje |
|---|---|
* | svaka vrednost |
5 | tačno ta vrednost |
1,15,30 | nabrajanje |
1-5 | opseg |
*/10 | svakih 10 jedinica |
9-17/2 | na 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
Post a Comment