Cron-lauseke koostuu viidestä välilyönnein erotetusta kentästä: minuutti, tunti, kuukauden päivä, kuukausi ja viikonpäivä. Niiden perään tulee suoritettava komento. 30 2 * * * tarkoittaa ”joka päivä klo 02.30”. Kenttään voi kirjoittaa luvun, tähden * eli ”jokainen arvo”, pilkuilla erotetun luettelon, väliviivalla merkityn välin tai kauttaviivalla merkityn askeleen. Useimmat cron-ongelmat eivät johdu itse syntaksista vaan kaikesta sen ympärillä: palvelimen aikavyöhykkeestä, säännöstä, jolla kuukauden päivä ja viikonpäivä yhdistetään, sekä niukasta ympäristöstä, jossa cron ajaa komennot.
Tämä opas selittää jokaisen kentän ja erikoismerkin, antaa taulukon valmiita lausekkeita ja käy läpi virheet, joiden takia ajot käynnistyvät väärään aikaan tai eivät lainkaan.
Viisi kenttää
Jokainen käyttäjän crontabin rivi noudattaa samaa rakennetta:
┌───────────── minuutti (0–59)
│ ┌─────────── tunti (0–23)
│ │ ┌───────── kuukauden päivä (1–31)
│ │ │ ┌─────── kuukausi (1–12 tai JAN–DEC)
│ │ │ │ ┌───── viikonpäivä (0–7 tai SUN–SAT, 0 ja 7 ovat molemmat sunnuntai)
│ │ │ │ │
* * * * * /path/to/command
Ajo käynnistyy, kun kuluva minuutti vastaa kaikkia kenttiä. Poikkeuksena ovat kaksi päiväkenttää, joista kerrotaan alempana. Kuukaudet ja viikonpäivät voi kirjoittaa kolmikirjaimisina englanninkielisinä niminä, eikä kirjainkoolla ole väliä.
Omaa crontabia muokataan komennolla crontab -e ja sen sisällön näkee komennolla crontab -l. Järjestelmänlaajuisissa tiedostoissa, /etc/crontab ja hakemiston /etc/cron.d/ tiedostot, on aikataulun ja komennon välissä kuudes kenttä: käyttäjä, jona ajo suoritetaan. Rivin kopioiminen muodosta toiseen lisäämättä tai poistamatta tätä kenttää on klassinen tapa rikkoa ajo.
Erikoismerkit
MerkkiMerkitysEsimerkkiTulos*Jokainen arvo* * * * *Joka minuutti,Arvojen luettelo0 8,12,18 * * *Klo 08.00, 12.00 ja 18.00-Väli0 9 * * 1-5Klo 09.00 maanantaista perjantaihin/Askel*/15 * * * *Minuutit 0, 15, 30 ja 45
Miten askeleet todella toimivat
Askel jakaa kentän arvoalueen alkaen sen ensimmäisestä arvosta. */15 minuuttikentässä tarkoittaa minuutteja 0, 15, 30 ja 45. Askeleen voi liittää myös väliin: 0-30/10 tarkoittaa minuutteja 0, 10, 20 ja 30.
Askeleet alkavat alusta kentän rajalla. */7 minuuttikentässä käynnistyy minuuteilla 0, 7, 14 ja niin edelleen 56:een asti ja sitten taas minuutilla 0, joten tunnin viimeinen väli on vain neljä minuuttia. */7 ei siis tarkoita ”seitsemän minuutin välein”. Klassisella cronilla ei myöskään voi ilmaista ”90 minuutin välein” yhdellä rivillä; tarvitset kaksi riviä tai tarkistuksen skriptin sisällä.
Syntaksi, joka ei ole klassista cronia
Dokumentaatiossa voi näkyä merkit L (viimeinen), W (lähin arkipäivä), # (kuukauden n:s viikonpäivä) ja ?. Ne ovat peräisin Quartzista ja joistakin pilvi- ja CI-ajastimista, eivät Linux-palvelimen cronista, ja osa näistä ajastimista lisää alkuun myös sekuntikentän. Monet cron-toteutukset eivät myöskään hyväksy nimistä muodostettuja välejä, joten kirjoita 1-5 äläkä MON-FRI.
Pikakomennot, kuten @daily
Useimmat Linuxin cron-toteutukset hyväksyvät viiden kentän sijaan nimetyn pikakomennon:
@reboot: kerran, kun cron-palvelu käynnistyy uudelleenkäynnistyksen jälkeen.
@yearly tai @annually: 0 0 1 1 *, keskiyöllä 1. tammikuuta.
@monthly: 0 0 1 * *, keskiyöllä kuukauden ensimmäisenä päivänä.
@weekly: 0 0 * * 0, keskiyöllä lauantain ja sunnuntain välillä.
@daily tai @midnight: 0 0 * * *.
@hourly: 0 * * * *.
Kaikki pikakomennot käynnistyvät tasatunnein tai keskiyöllä, joten kiireisellä palvelimella jokainen ajo kilpailee samoista resursseista klo 00.00. Kun kirjoitat koko lausekkeen ja valitset epätavallisen minuutin, kuten 17 0 * * *, kuorma jakautuu tasaisemmin.
Valmiit cron-lausekkeet
LausekeKäynnistyy* * * * *Joka minuutti*/5 * * * *5 minuutin välein*/15 * * * *15 minuutin välein0 * * * *Joka tunti tasalta15 */2 * * *Joka toisen tunnin minuutilla 15: 00.15, 02.15, 04.15 ja niin edelleen0 9-17 * * 1-5Joka tunti klo 09.00–17.00 maanantaista perjantaihin*/10 8-18 * * 1-510 minuutin välein toimistoaikaan arkipäivisin30 2 * * *Joka päivä klo 02.300 8,12,18 * * *Kolmesti päivässä: 08.00, 12.00 ja 18.000 6 * * 1Joka maanantai klo 06.000 22 * * 5Joka perjantai klo 22.000 0 * * 0Joka sunnuntai keskiyöllä0 3 1 * *Jokaisen kuukauden ensimmäisenä päivänä klo 03.000 4 1,15 * *Jokaisen kuukauden 1. ja 15. päivänä klo 04.000 5 1 */3 *Neljännesvuosittain: 1. tammikuuta, huhtikuuta, heinäkuuta ja lokakuuta klo 05.000 0 1 1 *Kerran vuodessa, keskiyöllä 1. tammikuuta@rebootKerran jokaisen järjestelmän käynnistyksen jälkeen
Tähän listaan liittyvä yleinen virhe on * */2 * * *. Se ei käynnisty kahden tunnin välein, vaan joka minuutti joka toisen tunnin ajan, kuusikymmentä kertaa peräkkäin. Kun rajaat tunnin, aseta aina myös minuutti.
Kuukauden päivä ja viikonpäivä: TAI-sääntö
Kaikki kentät yhdistetään JA-ehdolla, paitsi kaksi päiväkenttää. Kun sekä kuukauden päivä että viikonpäivä on rajattu eli kumpikaan ei ole *, ajo käynnistyy, kun jompikumpi täsmää. Siksi tämä rivi:
0 9 1 * 1 /usr/local/bin/report.sh
käynnistyy klo 09.00 jokaisen kuukauden ensimmäisenä päivänä ja klo 09.00 joka maanantai, ei vain niinä maanantaina, jotka osuvat kuun ensimmäiselle päivälle. Samasta syystä 0 9 1-7 * 1 ei tarkoita ”kuukauden ensimmäinen maanantai”; se käynnistyy päivinä 1–7 ja joka maanantai. Ensimmäisen maanantain saat ajastamalla päivät 1–7 ja tarkistamalla viikonpäivän komennossa. Huomaa kenoviivalla suojattu prosenttimerkki, josta kerrotaan alempana:
0 9 1-7 * * [ ”$(date +\%u)” = ”1” ] && /usr/local/bin/report.sh
Klassisessa cronissa ei ole myöskään ”kuukauden viimeistä päivää”. GNU:n date-komennolla voit ajastaa päivät 28–31 ja käynnistää ajon vain, kun huomenna on kuun ensimmäinen päivä:
0 23 28-31 * * [ ”$(date -d tomorrow +\%d)” = ”01” ] && /usr/local/bin/month-end.sh
Aikavyöhykkeet ja kesäaika
Cron käyttää sen järjestelmän aikavyöhykettä, jossa se toimii. Tukholman aikaan kirjoitettu ajo UTC-ajassa olevalla palvelimella käynnistyy vuodenajasta riippuen tunnin tai kaksi väärään aikaan. Tarkista palvelimen aikavyöhyke komennolla timedatectl tai date ennen kuin valitset aikataulun. Käytä samaa aikavyöhykettä myös ajon valvonnassa: Uptimecheckin cron-valvonnat ottavat crontabin aikataulun yhdessä aikavyöhykkeen kanssa, joten odotetut ajoajat vastaavat palvelimen aikaa.
Jotkin toteutukset, kuten cronie, hyväksyvät crontabin alussa CRON_TZ-muuttujan, jolla aikataulut ajetaan toisella aikavyöhykkeellä. Tuki vaihtelee cron-versioiden välillä, joten testaa se äläkä oleta sen toimivan.
Kesäaika aiheuttaa kaikkein oudoimmat virheet. Keväällä yksi paikallinen tunti jää kokonaan väliin, syksyllä yksi tunti toistuu kahdesti. Noin klo 01.00–03.00 paikallista aikaa ajastettu ajo voi jäädä väliin, myöhästyä tai käynnistyä kahdesti, ja eri cron-toteutukset käsittelevät muutoksen eri tavoin. Turvallisimmat vaihtoehdot:
Pidä palvelimet UTC-ajassa, jossa ei ole kesäaikaa, ja muunna ajat päässä tai kommentissa.
Jos palvelimen on oltava paikallisessa ajassa, pidä tärkeät ajot poissa tunneilta, joina kelloja siirretään.
Kirjoita aikavyöhyke kommenttiin jokaisen ajon yläpuolelle, jottei seuraavan ihmisen tarvitse arvata.
Tee ajoista sellaisia, että ne voi turvallisesti ajaa kahdesti, esimerkiksi tarkistamalla, onko päivän vienti jo olemassa.
Ympäristön ja PATH-muuttujan sudenkuopat
Jos komento toimii terminaalissa mutta epäonnistuu cronissa, syy on lähes aina ympäristö. Cron ei lataa komentotulkkisi profiilia, joten moni itsestäänselvyys puuttuu:
PATH on minimaalinen, usein pelkkä /usr/bin:/bin. Hakemiston /usr/local/bin komentoja tai nvm:llä, pyenvillä, rbenvillä tai Composerilla asennettuja työkaluja ei löydy. Käytä absoluuttisia polkuja tai aseta PATH crontabin alussa.
Komentotulkki on /bin/sh, ei bash. Pelkästään bashin syntaksi, kuten [[ ]] tai source, epäonnistuu. Aseta SHELL=/bin/bash tai siirrä logiikka skriptiin, jossa on bashin shebang-rivi.
Prosenttimerkit ovat erikoismerkkejä. Crontabin rivillä % muuttuu rivinvaihdoksi. date +%F on kirjoitettava muodossa date +\%F tai siirrettävä skriptiin.
Työhakemisto on käyttäjän kotihakemisto, ei projektisi. Suhteelliset polut osoittavat väärään paikkaan. Siirry ensin projektiin komennolla cd.
Ympäristömuuttujat puuttuvat. Tiedostossa .bashrc exportatut API-avaimet ja tietokantojen URL-osoitteet eivät ole olemassa. Lataa ne skriptissä tiedostosta.
Tuloste katoaa. Cron lähettää tulosteen sähköpostilla osoitteeseen MAILTO, jos sähköposti on määritetty, eikä se useimmilla palvelimilla ole. Ohjaa tuloste lokitiedostoon.
Ajot voivat mennä päällekkäin. Jos viiden minuutin välein käynnistyvä ajo kestää joskus seitsemän minuuttia, kaksi kopiota on käynnissä yhtä aikaa. flock -n ohittaa ajon, kun edellinen pitää vielä lukkoa.
Jotkin cron-versiot ohittavat myös viimeisen rivin, joka ei pääty rivinvaihtoon. Crontab, joka huomioi kaiken tämän, näyttää tältä:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=””
# Yöllinen tietokannan varmuuskopio. Palvelimen aika on UTC.
30 2 * * * cd /var/www/fjordstudio && flock -n /tmp/backup.lock ./bin/backup.sh >> /var/log/backup.log 2>&1
Näin testaat cron-lausekkeen
Lue se sanoina. Liitä lauseke cron-lausekkeiden tulkkiin ja tarkista, että kuvaus ja seuraavat ajoajat vastaavat sitä, mitä tarkoitit.
Aja komento cronin ympäristössä. Riisuttu ympäristö toistaa useimmat ”toimii minun terminaalissani” -virheet ennen kuin joudut odottamaan aikataulua.
Ajasta se kerran joka minuutille. Käytä väliaikaisesti lauseketta * * * * *, katso että ajo käynnistyy, ja aseta sitten oikea aikataulu.
Tarkista, että cron käynnisti sen. Debianissa ja Ubuntussa grep CRON /var/log/syslog tai journalctl -u cron; Red Hat -pohjaisissa järjestelmissä /var/log/cron tai journalctl -u crond.
Varmista, että crontab on asennettu komennolla crontab -l sen käyttäjän tunnuksella, jonka pitäisi ajaa se.
Cronin ympäristön voi simuloida komentotulkissa näin:
env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME=”$HOME” /bin/sh -c ’/usr/local/bin/backup.sh’
Liitä jokaiseen ajoon heartbeat
Oikea lauseke kertoo cronille vain, milloin ajo käynnistetään. Se ei kerro mitään siitä, ajettiinko ajo tai valmistuiko se. Uudelleenkäynnistys, ylikirjoitettu crontab tai puuttuva muuttuja epäonnistuvat kaikki hiljaa.
Heartbeat paikkaa tämän aukon. Ajo kutsuu yksilöllistä URL-osoitetta, kun se valmistuu onnistuneesti, ja valvontapalvelu hälyttää, jos kutsua ei tule aikataulussa:
30 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 –retry 3 https://heartbeat.example.com/your-unique-id > /dev/null
Aseta heartbeatin odotettu väli samaksi kuin cron-lausekkeen aikataulu ja jätä pelivaraa hitaille ajoille: 24 tuntia ja vähän päälle yölliselle ajolle, tunti ja vähän päälle tunneittaiselle. Uptimecheckin cron-jobien valvonta toimii näin: se hälyttää, kun ping puuttuu, ja lähettää palautumisilmoituksen, kun ajo kuittaa taas. Sen cron-valvonnat ottavat crontabin aikataulun omalla aikavyöhykkeelläsi, hyväksyvät aloitus- ja lopetuspingit samaan valvontaan, hälyttävät, kun ajo ylittää enimmäiskestonsa, ja voivat tallentaa poistumiskoodin ja ajon tulosteen. Opas cron-jobien valvonnasta heartbeateilla käy käyttöönoton läpi yksityiskohtaisesti, ja väliin jäävien cron-tehtävien estäminen kertoo siihen liittyvistä käytännöistä.
Kun heartbeat jää tulematta, syy on usein palvelimessa: täysi levy, loppunut muisti tai suunnittelematon uudelleenkäynnistys. Palvelinvalvonta heartbeatien rinnalla näyttää syyn samalla hetkellä.
Yleisten virheiden tarkistuslista
Tunti rajataan, mutta minuutiksi jätetään *.
Molemmat päiväkentät asetetaan ja odotetaan JA-ehtoa TAI-ehdon sijaan.
Oletetaan, että palvelin on samalla aikavyöhykkeellä kuin sinä.
Tärkeitä ajoja ajastetaan kesäajan vaihtumisen tunnille.
Käytetään suhteellisia polkuja, bashin syntaksia tai suojaamatonta %-merkkiä.
Ajo pyörii ilman heartbeatia, joten kukaan ei huomaa, kun se pysähtyy.
Yhteenveto
Viisi kenttää, neljä erikoismerkkiä ja kourallinen pikakomentoja kattavat lähes kaikki tarvitsemasi aikataulut. Lauseke on harvoin ongelma. Aikavyöhykkeet, päiväkenttien TAI-sääntö ja cronin riisuttu ympäristö ovat. Kirjoita aikavyöhyke jokaisen ajon viereen, käytä absoluuttisia polkuja, kirjaa tuloste lokiin ja anna jokaiselle tärkeälle ajolle heartbeat.
Uptimecheckin heartbeatit sisältyvät jokaiseen pakettiin, myös Free-pakettiin, käytettävyyden, SSL:n, verkkotunnusten ja DNS:n valvonnan rinnalla. Aloita 14 päivän ilmainen kokeilu, luottokorttia ei tarvita.