Jak czytać wyrażenie cron
Wyrażenie cron to pięć wartości rozdzielonych spacjami, czytanych od lewej do prawej jako minuta, godzina, dzień miesiąca, miesiąc, dzień tygodnia. Zadanie uruchamia się wtedy, gdy bieżący czas pasuje do każdego pola.
30 4 * * 1
│ │ │ │ │
│ │ │ │ └── day of week (1 = Monday)
│ │ │ └──── month (any)
│ │ └────── day of month (any)
│ └──────── hour (4am)
└─────────── minute (30)
To wyrażenie czyta się jako "o 04:30 w każdy poniedziałek".
Pięć pól
| # | Pole | Dozwolone wartości | Uwagi |
|---|---|---|---|
| 1 | Minuta | 0 do 59 | |
| 2 | Godzina | 0 do 23 | Zegar 24 godzinny, 0 to północ |
| 3 | Dzień miesiąca | 1 do 31 | |
| 4 | Miesiąc | 1 do 12 albo JAN do DEC | |
| 5 | Dzień tygodnia | 0 do 6 albo SUN do SAT | 0 to niedziela, a większość implementacji cron przyjmuje również 7 |
Część harmonogramów używa innego kształtu. Quartz, wykorzystywany przez wiele oprogramowania javowego, stawia sekundy na początku i dokłada opcjonalny rok, a dni tygodnia numeruje od 1 do 7, zaczynając od niedzieli. Jeśli wyrażenie ma sześć albo siedem pól, sprawdź, dla którego systemu zostało napisane, zanim zaufasz swojemu odczytowi.
Operatory
Są cztery i łączą się ze sobą wewnątrz pojedynczego pola.
| Symbol | Nazwa | Przykład | Znaczenie |
|---|---|---|---|
* | Dowolna wartość | * * * * * | Co minutę każdego dnia |
, | Lista | 0 9,13,17 * * * | O 09:00, 13:00 i 17:00 |
- | Zakres | 0 9-17 * * * | Co godzinę od 09:00 do 17:00 włącznie |
/ | Krok | */15 * * * * | O :00, :15, :30 i :45 |
Krok zawsze stosuje się do zakresu. */15 w polu minuty oznacza "zaczynając od 0, bierz co piętnastą wartość aż do 59". Krok można nałożyć również na jawny zakres: 5-30/10 daje 5, 15 i 25, a potem się kończy, ponieważ 35 wykracza poza koniec.
Kroki nie oznaczają "co 15 minut od teraz"; wybierają stałe wartości z tarczy zegara. */40 odpala o :00 i :40, a potem czeka tylko 20 minut na :00 kolejnej godziny, ponieważ zliczanie zaczyna się od nowa w każdej godzinie. Listy mogą zawierać zakresy i kroki, więc 0 0-6/2,12,18-23 * * * jest poprawnym polem godziny.
Nazwy i skróty
Pola miesiąca i dnia tygodnia przyjmują trzyliterowe nazwy, a wielkość liter nie ma znaczenia, więc JAN, jan i Jan to to samo. Klasyczna dokumentacja crontab mówi, że zakresy i listy nazw nie są dozwolone, choć wiele nowoczesnych implementacji przyjmuje MON-FRI. Jeśli nie masz pewności, co uruchamia twoje zadanie, używaj liczb: 1-5 jest jednoznaczne wszędzie.
Kilka skrótów zastępuje całe pięciopolowe wyrażenie:
| Skrót | Odpowiednik | Uruchamia się |
|---|---|---|
@yearly albo @annually | 0 0 1 1 * | O północy 1 stycznia |
@monthly | 0 0 1 * * | O północy pierwszego dnia miesiąca |
@weekly | 0 0 * * 0 | O północy w niedzielę |
@daily albo @midnight | 0 0 * * * | O północy codziennie |
@hourly | 0 * * * * | O pełnej godzinie |
Istnieje również @reboot, ale nie jest to harmonogram: uruchamia zadanie raz, w chwili startu samego crona.
Pułapka dnia miesiąca i dnia tygodnia
To ta, która gryzie. Kiedy zarówno pole dnia miesiąca, jak i pole dnia tygodnia są ograniczone, czyli żadne z nich nie jest *, cron uruchamia zadanie wtedy, gdy pasuje którekolwiek z nich, a nie wtedy, gdy pasują oba.
0 0 13 * 5
Można to odczytać jako "o północy w piątek trzynastego". W rzeczywistości oznacza to "o północy trzynastego dnia każdego miesiąca, a także o północy w każdy piątek": ponad sześćdziesiąt uruchomień rocznie zamiast jednego albo dwóch.
Oczekiwane zachowanie koniunkcji obowiązuje wyłącznie wtedy, gdy jedno z tych dwóch pól jest *. Zatem 0 0 * * 5 to każdy piątek, a 0 0 13 * * to każdy trzynasty dzień miesiąca, i oba są całkowicie normalne. To ograniczenie obu pól naraz włącza alternatywę.
Nie ma standardowego sposobu na wyrażenie "piątku trzynastego" w pięciu polach. Zwykłym obejściem jest zaplanowanie zadania na każdego trzynastego i sprawdzanie w samym zadaniu dnia tygodnia przed wykonaniem jakiejkolwiek pracy.
Pokrewna subtelność: część implementacji rozstrzyga, czy pole jest ograniczone, sprawdzając, czy dosłownie zaczyna się od *. Przy takich implementacjach 0-6 w polu dnia tygodnia liczy się jako ograniczenie, choć obejmuje każdy dzień, i po cichu włącza zachowanie alternatywy. Gdy masz na myśli "dowolny", używaj *.
Błędy, których warto szukać
* */2 * * *uruchamia zadanie co minutę w co drugiej godzinie: 720 uruchomień dziennie. Chodziło ci o0 */2 * * *, czyli o 12.- Brakujące pole minuty przesuwa wszystko o jedno w lewo i zwykle nadal się parsuje, dając poprawny harmonogram o zupełnie błędnej porze.
0 0 31 * *po cichu pomija miesiące, które nie mają trzydziestego pierwszego dnia.- Cron używa strefy czasowej systemu albo użytkownika, chyba że harmonogram pozwala ją ustawić. Kiedy zegary przesuwają się z powodu czasu letniego, zadanie z pominiętej godziny może w ogóle się nie uruchomić, a zadanie z godziny powtórzonej może uruchomić się dwa razy, zależnie od implementacji. Zadania, które muszą wykonać się raz dziennie, najbezpieczniej planować z dala od nocnych godzin, na które przypada przesunięcie.
W razie wątpliwości odczytaj wyrażenie z powrotem jako zdanie, a potem sprawdź kilka najbliższych terminów, w których naprawdę by odpaliło. Jeśli te daty nie są tym, co opisałeś, błędne jest wyrażenie, a nie twój odczyt.