Một biểu thức cron có năm trường cách nhau bằng dấu cách: phút, giờ, ngày trong tháng, tháng và ngày trong tuần. 0 9 * * 1-5 đọc là "ở phút 0 của giờ 9, vào bất kỳ ngày nào trong tháng, bất kỳ tháng nào, từ thứ Hai đến thứ Sáu", tức 9:00 các ngày thường. Mỗi trường có thể là một số, * cho mọi giá trị, một danh sách như 1,15, một khoảng như 9-17 hoặc một bước nhảy như */15. Bảng tra này liệt kê cú pháp, một loạt lịch dựng sẵn có giờ chạy đã được tính, quy tắc khiến gần như ai cũng bất ngờ (ngày trong tháng và ngày trong tuần hoạt động theo kiểu HOẶC), và các bẫy múi giờ cùng giờ mùa hè khiến tác vụ chạy sai giờ.
Năm trường
| Vị trí | Trường | Giá trị cho phép | Tên |
|---|---|---|---|
| 1 | Phút | 0 đến 59 | |
| 2 | Giờ | 0 đến 23 | |
| 3 | Ngày trong tháng | 1 đến 31 | |
| 4 | Tháng | 1 đến 12 | JAN đến DEC |
| 5 | Ngày trong tuần | 0 đến 7, trong đó 0 và 7 đều là Chủ nhật | SUN đến SAT |
Trường thứ sáu đặt trước các trường này là giây, theo bố cục của Spring và Quartz, nên */10 * * * * * là "mỗi 10 giây". Cron cổ điển không có giây; khoảng ngắn nhất của nó là một phút.
Bốn ký tự đặc biệt
| Ký tự | Ý nghĩa | Ví dụ |
|---|---|---|
* | Mọi giá trị | * * * * * chạy mỗi phút |
, | Một danh sách | 1,15 ở trường ngày là ngày 1 và ngày 15 |
- | Một khoảng, gồm cả hai đầu | 9-17 ở trường giờ là từ 9 đến 17 |
/ | Một bước nhảy | */15 là cứ 15 giá trị một lần; 10-30/5 là 10, 15, 20, 25, 30; 5/20 bắt đầu từ 5 và lặp lại mỗi 20 |
Tên dùng được trong danh sách và khoảng, chữ hoa hay thường đều được: MON-FRI, jan,jul. Các lối tắt này thay thế cả một biểu thức: @hourly là 0 * * * *, @daily và @midnight là 0 0 * * *, @weekly là 0 0 * * 0, @monthly là 0 0 1 * * và @yearly là 0 0 1 1 *.
Các lịch dựng sẵn
| Biểu thức | Nói bằng lời |
|---|---|
* * * * * | Mỗi phút |
*/5 * * * * | Mỗi 5 phút |
0 * * * * | Mỗi giờ, đúng đầu giờ |
0 */6 * * * | Mỗi 6 giờ: 00:00, 06:00, 12:00, 18:00 |
0 0 * * * | Mỗi ngày lúc nửa đêm |
0 9 * * 1-5 | 9:00 các ngày thường |
0 9-17 * * 1-5 | Đúng đầu giờ từ 9:00 đến 17:00 các ngày thường |
15 10 * * MON,WED,FRI | 10:15 các thứ Hai, thứ Tư và thứ Sáu |
0 0 1,15 * * | Nửa đêm ngày 1 và ngày 15 |
0 0 * * 0 | Nửa đêm mỗi Chủ nhật |
0 0 1 * * | Nửa đêm ngày 1 hằng tháng |
0 0 1 */3 * | Nửa đêm ngày 1 tháng 1, 4, 7 và 10 |
0 0 1 1 * | Nửa đêm ngày 1 tháng 1 |
0 0 29 2 * | Nửa đêm ngày 29 tháng 2, và chỉ ngày đó |
Đây là những gì một số lịch trên làm trên lịch thật, tính cho TP. Hồ Chí Minh (UTC+7) kể từ 10:00 thứ Ba ngày 13 tháng 10 năm 2026:
0 9 * * 1-5các lần chạy tới là thứ Tư 14, thứ Năm 15 và thứ Sáu 16 tháng 10, rồi thứ Hai 19 tháng 10 lúc 09:00. Thứ Bảy và Chủ nhật bị bỏ qua.0 0 1,15 * *chạy vào 15 tháng 10, 1 tháng 11, 15 tháng 11 và 1 tháng 12, luôn lúc 00:00.0 0 29 2 *chạy vào 29 tháng 2 năm 2028, rồi 29 tháng 2 năm 2032.
Bước nhảy không chia đều
Bước nhảy được đếm từ đầu khoảng giá trị của trường, và bắt đầu lại khi chu kỳ kế tiếp bắt đầu. */7 ở trường phút nghĩa là các phút 0, 7, 14, 21, 28, 35, 42, 49 và 56, rồi lại 0 ở đầu giờ kế tiếp. Khoảng cách từ 56 đến 00 là 4 phút chứ không phải 7. Bước nhảy chỉ chạy đều khi nó chia hết trường: với phút đó là 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 và 30. 5-59/15 cho 5, 20, 35 và 50. "Mỗi 7 phút" thật sự không thể viết bằng một dòng cron: hãy cho tác vụ chạy mỗi phút và để nó tự kiểm tra lần chạy trước cách đây bao lâu, hoặc dùng bộ lập lịch hỗ trợ khoảng thời gian thuần túy.
Ngày trong tháng và ngày trong tuần là HOẶC
Khi cả trường ngày trong tháng lẫn trường ngày trong tuần đều bị giới hạn, cron cổ điển chạy tác vụ khi một trong hai khớp, chứ không phải khi cả hai cùng khớp. Vì vậy 0 0 13 * 5 không có nghĩa là "thứ Sáu ngày 13". Nó có nghĩa là "mọi ngày 13, và mọi thứ Sáu". Trong tháng 10 năm 2026 nó chạy vào các ngày 2, 9, 13, 16, 23 và 30.
Hai cách để có đúng điều bạn muốn:
- Chỉ giới hạn một trường trong lịch và kiểm tra trường kia bên trong tác vụ. Với thứ Sáu ngày 13, đặt lịch
0 0 13 * *và cho script thoát nếu hôm nay không phải thứ Sáu. - Để chạy vào ngày cuối tháng, đặt lịch
0 0 28-31 * *và kiểm tra trong lệnh xem ngày mai có phải mùng 1 không. Trong crontab, dấu phần trăm phải viết là\%, như[ "$(date -d tomorrow +\%d)" = "01" ] && /path/job.sh(datecủa GNU).
Trong các bản cài đặt cổ điển kiểu Vixie, một trường bắt đầu bằng * được coi là không bị giới hạn theo quy tắc này, kể cả */2. Vì thế 0 0 */2 * 5 không phải là HOẶC: nó có nghĩa là các ngày lẻ trong tháng mà cũng là thứ Sáu. Năm 2026 điều đó cho ngày 9 và 23 tháng 10, rồi 13 và 27 tháng 11. Các bộ lập lịch khác, như Quartz hay những bộ tích hợp sẵn trong một số framework, xử lý khác hoặc từ chối, nên hãy luôn xem tài liệu của bộ bạn dùng.
Cron cổ điển không có gì
Các ký tự ?, L, W và # ("ngày cuối", "ngày làm việc gần nhất", "thứ Hai thứ hai") cùng trường năm thuộc về các bộ lập lịch Quartz và Spring, không thuộc crontab cổ điển.
Múi giờ
Biểu thức cron không có múi giờ. Bộ lập lịch dùng múi giờ của máy, hoặc một thiết lập của dịch vụ. Máy chủ rất thường để UTC, nên 0 9 * * 1-5 có thể nghĩa là 09:00 UTC, tức 16:00 ở TP. Hồ Chí Minh, chứ không phải 09:00 giờ địa phương. Hãy xác định múi giờ trước rồi mới viết giờ. Việt Nam không dùng giờ mùa hè nên tác vụ ở đây không bao giờ bị lệch, nhưng máy chủ ở New York hay London thì có.
Giờ mùa hè
Vào ngày đồng hồ được chỉnh, một giờ địa phương có thể biến mất hoặc xảy ra hai lần. Với New York năm 2026:
30 2 * * *lẽ ra chạy lúc 02:30 mỗi ngày. Ngày 8 tháng 3 năm 2026 đồng hồ nhảy thẳng từ 01:59 lên 03:00, nên 02:30 không tồn tại. Bộ lập lịch bỏ qua giờ bị thiếu sẽ chạy tác vụ vào ngày 7 tháng 3 rồi ngày 9 tháng 3, không có gì ngày 8.30 1 * * *lẽ ra chạy lúc 01:30. Ngày 1 tháng 11 năm 2026 đồng hồ lùi từ 02:00 về 01:00, nên 01:30 xảy ra hai lần, một lần theo giờ mùa hè và một lần theo giờ mùa đông. Bộ lập lịch có thể chạy một lần hoặc hai lần.
Các bộ lập lịch thật xử lý chỗ này khác nhau, và danh sách lần chạy tiếp theo của công cụ giải thích cron tuân theo một quy tắc đã nêu rõ: giờ không tồn tại bị bỏ qua, còn giờ xảy ra hai lần chỉ chạy một lần, ở lần xuất hiện đầu tiên. Thói quen an toàn là đặt lịch các tác vụ quan trọng theo UTC, hoặc ít nhất tránh khung 00:00 đến 03:00 của múi giờ bạn, và làm cho mọi tác vụ chạy hai lần hay bị bỏ một lần đều không gây hại. Bài về dấu thời gian Unix và múi giờ giải thích vì sao cùng một thời điểm lại có các số đọc đồng hồ khác nhau.
Kiểm tra biểu thức bằng công cụ
- Mở công cụ giải thích cron rồi gõ hoặc dán biểu thức. Các lịch có sẵn như "Mỗi 5 phút" và "Ngày thường lúc 9:00" sẽ điền giúp bạn.
- Đọc câu ở mục "Nói bằng lời" và bảng "Từng trường".
- Chọn Múi giờ mà bộ lập lịch của bạn dùng. Danh sách "10 lần chạy tiếp theo" được tính theo múi giờ đó, với các lần đổi giờ thật từ dữ liệu múi giờ của trình duyệt. Hãy so với điều bạn mong đợi, nhất là quanh cuối tháng và cuối tuần.
- Đọc mọi ghi chú về quy tắc ngày hoặc giờ mùa hè trước khi triển khai, và viết lại biểu thức bằng các trường thông thường nếu công cụ gọi tên một ký tự không được hỗ trợ.
Mọi thứ được tính trong trình duyệt, và biểu thức không được gửi đi đâu. Khi sửa crontab và muốn thấy điều gì đã đổi, hãy dán bản cũ và bản mới vào công cụ so sánh văn bản. Để đọc các dấu thời gian trong nhật ký của một tác vụ, hãy dùng công cụ đổi dấu thời gian.
Những lỗi thường gặp
- *Dùng `/n
vớinkhông chia hết khoảng giá trị**, như*/7`. - Mong ngày trong tháng và ngày trong tuần kết hợp theo kiểu VÀ.
- Quên rằng trường giây ở đầu làm mọi trường khác lùi một vị trí.
- Cho rằng máy chủ dùng giờ địa phương của bạn.
- Trông chờ vào môi trường shell của bạn. Tác vụ chạy với môi trường tối thiểu, nên hãy dùng đường dẫn tuyệt đối.
Danh sách kiểm tra ngắn
Đếm đủ năm trường, hoặc sáu nếu có giây. Kiểm tra bước nhảy chia hết. Nhớ rằng ngày trong tháng và ngày trong tuần cùng bị giới hạn nghĩa là "một trong hai". Biết múi giờ của bộ lập lịch, tránh các giờ quanh lúc đổi đồng hồ, và đọc mười lần chạy tiếp theo trước khi lưu.