Et cron-uttrykk består av fem felt atskilt med mellomrom: minutt, time, dag i måneden, måned og ukedag, etterfulgt av kommandoen som skal kjøres. 30 2 * * * betyr «kl. 02:30 hver dag». Hvert felt tar et tall, en * for «alle verdier», en liste med kommaer, et intervall med bindestrek eller et steg med skråstrek. De fleste cron-problemer skyldes ikke selve syntaksen, men det rundt den: serverens tidssone, regelen for hvordan dag i måneden og ukedag kombineres, og det minimale miljøet cron kjører kommandoene i.
Denne guiden forklarer hvert felt og hvert spesialtegn, gir deg en tabell med ferdige uttrykk og går gjennom feilene som får jobber til å kjøre til feil tid, eller ikke i det hele tatt.
De fem feltene
Hver linje i en bruker-crontab følger samme oppsett:
┌───────────── minutt (0–59)
│ ┌─────────── time (0–23)
│ │ ┌───────── dag i måneden (1–31)
│ │ │ ┌─────── måned (1–12 eller JAN–DEC)
│ │ │ │ ┌───── ukedag (0–7 eller SUN–SAT, både 0 og 7 er søndag)
│ │ │ │ │
* * * * * /path/to/command
En jobb kjøres når gjeldende minutt stemmer med alle feltene, med ett unntak for de to dagfeltene, som vi går gjennom nedenfor. Måneder og ukedager kan skrives som engelske navn på tre bokstaver, og det spiller ingen rolle om du bruker store eller små bokstaver.
Du redigerer din egen crontab med crontab -e og viser den med crontab -l. Systemfilene, /etc/crontab og filene i /etc/cron.d/, har et sjette felt mellom tidsplanen og kommandoen: brukeren jobben kjøres som. Å kopiere en linje fra det ene formatet til det andre uten å legge til eller fjerne det feltet er en klassisk måte å ødelegge en jobb på.
Spesialtegn
TegnBetydningEksempelResultat*Alle verdier* * * * *Hvert minutt,Liste med verdier0 8,12,18 * * *Kl. 08:00, 12:00 og 18:00-Intervall0 9 * * 1-5Kl. 09:00 mandag til fredag/Steg*/15 * * * *Minutt 0, 15, 30 og 45
Slik fungerer steg egentlig
Et steg deler opp verdiområdet til et felt, med start fra den første verdien. */15 i minuttfeltet betyr 0, 15, 30 og 45. Et steg kan også brukes på et intervall: 0-30/10 betyr minutt 0, 10, 20 og 30.
Steg starter på nytt ved feltets grense. */7 i minuttfeltet kjører på 0, 7, 14 og så videre opp til 56, og så på 0 igjen, slik at det siste mellomrommet hver time bare er fire minutter. */7 er altså ikke «hvert sjuende minutt». Klassisk cron kan heller ikke uttrykke «hvert 90. minutt» på én linje; da trenger du to linjer eller en sjekk inne i skriptet.
Syntaks som ikke er klassisk cron
I dokumentasjon kan du se L (siste), W (nærmeste hverdag), # (n-te ukedag i måneden) og ?. De kommer fra Quartz og enkelte sky- og CI-planleggere, ikke fra cron på en Linux-server, og noen av disse planleggerne legger også til et sekundfelt først. Mange cron-varianter avviser dessuten intervaller med navn, så skriv 1-5 i stedet for MON-FRI.
Snarveier som @daily
De fleste cron-implementasjoner på Linux godtar en navngitt snarvei i stedet for de fem feltene:
@reboot: én gang, når cron-daemonen starter etter en omstart.
@yearly eller @annually: 0 0 1 1 *, midnatt 1. januar.
@monthly: 0 0 1 * *, midnatt den første i måneden.
@weekly: 0 0 * * 0, midnatt mellom lørdag og søndag.
@daily eller @midnight: 0 0 * * *.
@hourly: 0 * * * *.
Alle snarveiene slår til på hel time eller ved midnatt, så på en travel server konkurrerer alle jobbene om de samme ressursene kl. 00:00. Skriver du hele uttrykket med et skjevt minutt, for eksempel 17 0 * * *, sprer du belastningen.
Ferdige cron-uttrykk
UttrykkKjører* * * * *Hvert minutt*/5 * * * *Hvert 5. minutt*/15 * * * *Hvert 15. minutt0 * * * *Hver time, på hel time15 */2 * * *Minutt 15 annenhver time: 00:15, 02:15, 04:15 og så videre0 9-17 * * 1-5Hver time fra 09:00 til 17:00, mandag til fredag*/10 8-18 * * 1-5Hvert 10. minutt i arbeidstiden på hverdager30 2 * * *Hver dag kl. 02:300 8,12,18 * * *Tre ganger om dagen: 08:00, 12:00 og 18:000 6 * * 1Hver mandag kl. 06:000 22 * * 5Hver fredag kl. 22:000 0 * * 0Hver søndag ved midnatt0 3 1 * *Den første dagen i hver måned kl. 03:000 4 1,15 * *Den 1. og 15. i hver måned kl. 04:000 5 1 */3 *Hvert kvartal: 1. januar, april, juli og oktober kl. 05:000 0 1 1 *Én gang i året, ved midnatt 1. januar@rebootÉn gang etter hver systemstart
En vanlig feil her er * */2 * * *. Det kjører ikke annenhver time. Det kjører hvert minutt i annenhver time, seksti ganger på rad. Når du begrenser timen, må du alltid angi minuttet også.
Dag i måneden og ukedag: ELLER-regelen
Alle felt kombineres med OG, bortsett fra de to dagfeltene. Når både dag i måneden og ukedag er begrenset, altså ingen av dem er *, kjøres jobben når ett av dem stemmer. Denne linjen:
0 9 1 * 1 /usr/local/bin/report.sh
kjører derfor kl. 09:00 den første i hver måned og kl. 09:00 hver mandag, ikke bare på mandager som faller på den første. Av samme grunn betyr ikke 0 9 1-7 * 1 «første mandag i måneden»; det kjører på dag 1 til 7 og på hver mandag. For å treffe første mandag planlegger du dag 1 til 7 og sjekker ukedagen i kommandoen. Legg merke til det escapede prosenttegnet, som forklares lenger ned:
0 9 1-7 * * [ «$(date +\%u)» = «1» ] && /usr/local/bin/report.sh
Klassisk cron har heller ingen «siste dag i måneden». Med GNU date planlegger du dag 28 til 31 og kjører bare når i morgen er den første:
0 23 28-31 * * [ «$(date -d tomorrow +\%d)» = «01» ] && /usr/local/bin/month-end.sh
Tidssoner og sommertid
Cron bruker tidssonen til systemet den kjører på. En jobb skrevet for Stockholm-tid på en server satt til UTC starter en eller to timer feil, avhengig av årstiden. Sjekk serverens tidssone med timedatectl eller date før du velger tidsplan. Bruk samme tidssone når du overvåker jobben: Uptimechecks cron-monitorer tar crontab-tidsplanen sammen med en tidssone, slik at forventede kjøretider stemmer med serverens.
Enkelte implementasjoner, som cronie, godtar en CRON_TZ-variabel øverst i crontab-en for å kjøre tidsplanene i en annen tidssone. Støtten varierer mellom cron-versjoner, så test det i stedet for å ta det for gitt.
Sommertid gir de merkeligste feilene. Om våren finnes én lokal time ikke; om høsten skjer én time to ganger. En jobb planlagt mellom omtrent 01:00 og 03:00 lokal tid kan bli hoppet over, forsinket eller kjørt to ganger, og hvordan hver cron-implementasjon håndterer overgangen, varierer. De tryggeste valgene:
Kjør serverne på UTC, som ikke har sommertid, og regn om i hodet eller i en kommentar.
Må serveren gå på lokal tid, hold viktige jobber utenfor timene da klokken stilles.
Skriv tidssonen i en kommentar over hver jobb, så neste person slipper å gjette.
Gjør jobbene trygge å kjøre to ganger, for eksempel ved å sjekke om dagens eksport allerede finnes.
Feller med miljø og PATH
En kommando som fungerer i terminalen, men feiler under cron, feiler nesten alltid på grunn av miljøet. Cron laster ikke skallprofilen din, så mye du tar for gitt, mangler:
PATH er minimal, ofte bare /usr/bin:/bin. Kommandoer i /usr/local/bin, eller verktøy installert med nvm, pyenv, rbenv eller Composer, blir ikke funnet. Bruk absolutte stier eller sett PATH øverst i crontab-en.
Skallet er /bin/sh, ikke bash. Syntaks som bare finnes i bash, som [[ ]] eller source, feiler. Sett SHELL=/bin/bash eller legg logikken i et skript med bash-shebang.
Prosenttegn er spesielle. I en crontab-linje blir % gjort om til et linjeskift. date +%F må skrives date +\%F, eller flyttes inn i et skript.
Arbeidskatalogen er brukerens hjemmekatalog, ikke prosjektet ditt. Relative stier peker feil sted. Gjør cd til prosjektet først.
Miljøvariablene er borte. API-nøkler og database-URL-er eksportert i .bashrc finnes ikke. Last dem fra en fil i skriptet.
Utdata forsvinner. Cron sender utdata på e-post til MAILTO hvis e-post er satt opp, og på de fleste servere er det ikke det. Send utdata til en loggfil.
Kjøringer kan overlappe. Hvis en jobb som går hvert femte minutt av og til tar sju, kjører to kopier samtidig. flock -n hopper over en kjøring mens den forrige holder låsen.
Noen cron-versjoner ignorerer også en siste linje som ikke slutter med linjeskift. En crontab som tar høyde for alt dette, ser slik ut:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=»»
# Nattlig databasebackup. Servertiden er UTC.
30 2 * * * cd /var/www/fjordstudio && flock -n /tmp/backup.lock ./bin/backup.sh >> /var/log/backup.log 2>&1
Slik tester du et cron-uttrykk
Les det tilbake med ord. Lim inn uttrykket i en cron-tolker og sjekk at beskrivelsen og de neste kjøretidene stemmer med det du mente.
Kjør kommandoen i crons miljø. Et nedstrippet miljø gjenskaper de fleste «fungerer i terminalen»-feil før du venter på tidsplanen.
Planlegg den hvert minutt én gang. Bruk * * * * * midlertidig, se at den kjører, og sett deretter den riktige tidsplanen.
Sjekk at cron startet den. På Debian og Ubuntu: grep CRON /var/log/syslog eller journalctl -u cron; på Red Hat-baserte systemer: /var/log/cron eller journalctl -u crond.
Bekreft at crontab-en er installert med crontab -l, som brukeren som skal kjøre den.
Slik simulerer du crons miljø fra et skall:
env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME=»$HOME» /bin/sh -c ‘/usr/local/bin/backup.sh’
Gi hver jobb en heartbeat
Et riktig uttrykk forteller bare cron når en jobb skal starte. Det sier ingenting om hvorvidt jobben faktisk kjørte eller ble ferdig. En omstart, en overskrevet crontab eller en manglende variabel feiler alle i stillhet.
En heartbeat tetter det hullet. Jobben kaller en unik URL når den er ferdig uten feil, og overvåkingstjenesten varsler deg når kallet ikke kommer som planlagt:
30 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 –retry 3 https://heartbeat.example.com/your-unique-id > /dev/null
Sett heartbeatens forventede intervall til samme tidsplan som cron-uttrykket, med margin for trege kjøringer: 24 timer pluss litt for en nattlig jobb, én time pluss litt for en jobb som går hver time. Uptimecheck overvåking av cron-jobber fungerer slik, med varsel når en ping mangler og beskjed når jobben melder seg igjen. Cron-monitorene tar crontab-tidsplanen i din tidssone, godtar start- og slutt-ping på samme monitor, varsler når en kjøring overskrider maksimal kjøretid, og kan lagre exit-koden og jobbens utdata. Guiden om hvordan du overvåker cron-jobber med heartbeats går gjennom oppsettet i detalj, og slik unngår du tapte cron-oppgaver tar for seg vanene rundt.
Når en heartbeat uteblir, ligger årsaken ofte på serveren: full disk, oppbrukt minne eller en uplanlagt omstart. Serverovervåking ved siden av heartbeatene viser årsaken i samme øyeblikk.
Sjekkliste over vanlige feil
Begrense timen, men la minuttet stå som *.
Sette begge dagfeltene og forvente OG i stedet for ELLER.
Anta at serveren er i din tidssone.
Legge viktige jobber i timen da sommertiden skifter.
Bruke relative stier, bash-syntaks eller % uten escape.
Kjøre en jobb uten heartbeat, så ingen merker når den stopper.
Oppsummering
Fem felt, fire spesialtegn og en håndfull snarveier dekker nesten alle tidsplaner du trenger. Uttrykket er sjelden problemet. Det er tidssoner, ELLER-regelen for dagfeltene og crons nakne miljø. Skriv tidssonen ved hver jobb, bruk absolutte stier, logg utdataene og gi hver jobb som betyr noe, en heartbeat.
Uptimecheck-heartbeats er inkludert i alle planer, også Free, sammen med oppetids-, SSL-, domene- og DNS-overvåking. Start en gratis prøveperiode på 14 dager, uten kredittkort.