Cron výrazy: pět polí, s příklady
Cron výraz je pět mezerou oddělených polí, která říkají, kdy se úloha spustí: minuta, hodina, den v měsíci, měsíc, den v týdnu. Čteno zleva doprava, 30 2 * * 1 znamená v minutě 30 hodiny 2, v libovolný den libovolného měsíce, pokud je tento den pondělí.
Pět polí
Každý standardní unixový řádek cron začíná stejnými pěti poli, za nimiž následuje příkaz ke spuštění.
* * * * * command to run
| | | | |
| | | | +-- day of week (0-7, 0 and 7 both mean Sunday, or SUN-SAT)
| | | +---- month (1-12, or JAN-DEC)
| | +------ day of month (1-31)
| +-------- hour (0-23)
+---------- minute (0-59)
Pole obsahuje jednu ze čtyř věcí: hvězdičku znamenající každou hodnotu, jedno číslo, seznam, nebo rozsah. Hodiny se zapisují ve 24hodinovém formátu bez AM či PM, takže 18:00 je 18. Neděle je zapsaná jako 0 i jako 7, protože se na tom různé systémy historicky neshodly, a cron přijímá obojí.
Některé plánovače přidávají další pole. Quartz, používaný mnoha Java frameworky, klade na začátek pole se sekundami a na konec volitelně přidává rok, takže šesti nebo sedmipolový výraz zkopírovaný z reference pro Quartz nebude v linuxovém crontabu fungovat. Než odkudkoli zkopírujete výraz, ověřte si, pro jakou variantu ho vlastně píšete.
Speciální znaky
*odpovídá každé hodnotě v poli.* * * * *se spustí každou minutu.,vypisuje hodnoty.0 8,13,20 * * *se spustí v 08:00, 13:00 a 20:00.-udává rozsah.0 9-17 * * *se spustí každou celou hodinu od 09:00 do 17:00./prochází rozsah krokem.*/15 * * * *se spustí v minutě 0, 15, 30 a 45. Dá se kombinovat s rozsahem:0 9-17/2 * * *se spustí v 9, 11, 13, 15 a 17.- Názvy.
MONažSUNaJANažDECfungují v posledních dvou polích a čtou se lépe než čísla. Uvnitř kroku se použít nedají.
V návodech se neustále objevují další čtyři znaky, které ve standardním cronu neexistují. L pro poslední den, W pro nejbližší pracovní den, # pro n-tý den v týdnu v daném měsíci a ? místo hvězdičky jsou rozšíření Quartz. Výraz jako 0 0 L * * linuxový crontab odmítne. Pro spuštění něčeho poslední den v měsíci tam místo toho spusťte úlohu denně a nechte rozhodnutí na příkazu:
0 0 * * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/month-end.sh
Všimněte si zpětných lomítek v tomto řádku. Znak procenta má v crontabu speciální význam, což je pátá chyba níže.
Cron také místo všech pěti polí přijímá šest zkratkových řetězců: @yearly (píše se i @annually), @monthly, @weekly, @daily (i @midnight), @hourly, a @reboot, který se spustí jednou při startu cronu, ne podle hodin. @reboot není podporovaný všude.
Běžné rozvrhy
| Kdy chcete úlohu spustit | Výraz |
|---|---|
| Každou minutu | * * * * * |
| Každých 5 minut | */5 * * * * |
| Každých 30 minut | 0,30 * * * * |
| Každou hodinu, přesně | 0 * * * * |
| Každé 2 hodiny | 0 */2 * * * |
| Každý den o půlnoci | 0 0 * * * |
| Každý den v 02:30 | 30 2 * * * |
| Dvakrát denně, 08:00 a 20:00 | 0 8,20 * * * |
| Pracovní dny v 09:00 | 0 9 * * MON-FRI |
| Každou hodinu v pracovní době, pracovní dny | 0 9-17 * * MON-FRI |
| Každé pondělí v 07:00 | 0 7 * * MON |
| Každou neděli v 03:15 | 15 3 * * SUN |
| Prvního v měsíci v 06:00 | 0 6 1 * * |
| Čtvrtletně, prvního ledna, dubna, července, října | 0 0 1 1,4,7,10 * |
Chyby, kvůli kterým úloha běží ve špatný čas
- Vyplnění obou polí pro den. Tohle napálí úplně každého. Když jsou den v měsíci i den v týdnu nastavené na něco jiného než hvězdičku, cron spustí úlohu, když sedí kterékoli z nich, ne obě zároveň.
0 0 13 * FRIse spustí každý 13. i každý pátek, ne jen v pátek třináctého. - Krok, který nedělí rozsah beze zbytku.
*/7 * * * *se spustí v minutách 0, 7, 14, 21, 28, 35, 42, 49 a 56, a pak znovu od 0. Mezera přes hranici hodiny je čtyři minuty, ne sedm. Stejná past platí pro*/40v poli minut a pro jakýkoli krok, který není dělitelem 60. - Umístění kroku do špatného pole.
*/2 * * * *znamená každé dvě minuty.0 */2 * * *znamená každé dvě hodiny. Vynechání úvodní0promění hodinovou úlohu v úlohu, která běží 30krát častěji. - Spoléhání na určité prostředí. Cron dá úloze minimální prostředí, obvykle málo víc než
PATH=/usr/bin:/binaSHELL=/bin/sh. Skript, který funguje ve vašem shellu, v cronu selže, protože volá něco v/usr/local/bin. Pro příkaz i uvnitř něj používejte absolutní cesty. - Neuvozený znak procenta. V crontabu se
%mění na nový řádek a všechno po prvním z nich se předá příkazu jako standardní vstup.date +%Y-%m-%dv řádku crontabu se musí zapsat jakodate +\%Y-\%m-\%d. - Ignorování výstupu. Cokoli úloha vypíše, se pošle e-mailem vlastníkovi crontabu, a na stroji bez nakonfigurované pošty se to zahodí. Pošlete si to někam, kde si to přečtete:
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 - Přesahující se běhy. Cron spustí další běh podle rozvrhu bez ohledu na to, jestli ten poslední doběhl. Dlouhé úlohy zabalte do zámku:
*/5 * * * * flock -n /tmp/sync.lock /usr/local/bin/sync.sh - Zapomenutý přechod na letní/zimní čas. Cron používá lokální čas stroje. Ve dnech, kdy se posouvají hodiny, hodina kolem 02:00 buď neexistuje, nebo nastane dvakrát, takže úloha naplánovaná do ní může být podle konkrétní implementace cronu přeskočena, nebo spuštěna dvakrát. Nastavte servery na UTC, nebo plánujte mimo toto okno.
- Napsání
crontab -r. Smaže celý crontab bez jakéhokoli potvrzení a na klávesnici sedí hned vedlecrontab -e. Udržujte crontab ve verzovacím systému a instalujte ho ze souboru.
Ověřte to zvenčí
Výraz, který se dá naparsovat, není totéž co úloha, která proběhla. Ověřte obojí, nejdřív na stroji, pak zvenčí.
Na stroji ověřte, co je nainstalované, co říkají hodiny a jestli cron úlohu spustil:
crontab -l
timedatectl
grep CRON /var/log/syslog | tail -20
journalctl -u cron -u crond --since "2 hours ago"
Řádek v logu dokazuje, že cron příkaz spustil. Nic ale neříká o tom, jestli příkaz uspěl, a proto na přesměrování do log souboru z chyb výše záleží.
Pak výsledek ověřte tak, jak by to udělal uživatel, zvenčí serveru. Většina naplánovaných úloh existuje proto, aby změnila něco pozorovatelného: feed, který by měl nést dnešní datum, sitemapu, která měla být přepsaná, export, který se měl objevit. Vyžádejte si to a přečtěte hlavičky:
curl -sI https://example.com/exports/daily.json
curl -s https://example.com/health/last-run
Hlavička Last-Modified řekne, jestli je soubor čerstvý, a to bez potřeby přístupu k shellu. Spuštění stejného požadavku z více lokalit pomocí HTTP kontroly odliší úlohu, která neproběhla, od stránky, která je cachovaná na edge uzlu v jednom regionu a zastaralá jen tam. Tento rozdíl je z jednoho curl na samotném serveru neviditelný.
Jak poznat, že naplánovaná úloha přestala běžet
Úloha cron, která přestane běžet, nevytvoří nic, čeho by si šlo všimnout. Neexistuje žádná chybová stránka ani neúspěšný požadavek, takže nic nespustí upozornění, pokud něco její nepřítomnost aktivně nehlídá. Sledujete efekt úlohy, ne úlohu samotnou: stavový soubor, který přepisuje, časovou značku, kterou publikuje, endpoint, který hlásí poslední úspěšný běh. Naplánovaná kontrola proti takovému endpointu promění tiché selhání v upozornění, a HostTracker je posílá e-mailem, SMS, hlasovým hovorem, přes Slack, Telegram a dalšími kanály napříč 13 typy monitorů. Postup nastavení je v návodu na HTTP kontrolu, další návody na řešení problémů najdete v clusteru oprav a úplný seznam typů kontrol je na stránce funkcí.