Giải thích biểu thức Cron: Hướng dẫn thực tế kèm 20 ví dụ
Hiểu 5 trường của biểu thức cron, các ký tự đặc biệt *, /, - và dấu phẩy, những lịch chạy phổ biến và các cạm bẫy khiến cron job chạy sai giờ.
Cron là trình lập lịch kinh điển của Unix, và cú pháp của nó đã lan rộng ra khỏi máy chủ Linux: Kubernetes CronJob, GitHub Actions, AWS EventBridge, Vercel cron, Laravel hay các thư viện Node đều dùng biểu thức giống (hoặc gần giống) nhau. Vậy mà */15 9-17 * * 1-5 vẫn khiến nhiều lập trình viên bối rối. Bài viết này giải thích cú pháp từng bước một.
Năm trường
Một biểu thức cron chuẩn gồm 5 trường cách nhau bởi dấu cách:
┌───────────── phút (0-59)
│ ┌─────────── giờ (0-23)
│ │ ┌───────── ngày trong tháng (1-31)
│ │ │ ┌─────── tháng (1-12 hoặc JAN-DEC)
│ │ │ │ ┌───── thứ trong tuần (0-7 hoặc SUN-SAT, 0 và 7 đều là Chủ nhật)
│ │ │ │ │
* * * * * lệnh cần chạy
Job sẽ chạy khi tất cả các trường khớp với thời điểm hiện tại (có một ngoại lệ liên quan đến ngày, sẽ nói ở dưới).
Các ký tự đặc biệt
| Ký hiệu | Ý nghĩa | Ví dụ | Đọc là |
|---|---|---|---|
* |
Mọi giá trị | * * * * * |
Mỗi phút |
, |
Danh sách | 0 9,18 * * * |
Lúc 09:00 và 18:00 |
- |
Khoảng | 0 9-17 * * * |
Mỗi giờ từ 09:00 đến 17:00 |
/ |
Bước nhảy | */10 * * * * |
Mỗi 10 phút |
Có thể kết hợp: 0-30/10 nghĩa là các phút 0, 10, 20 và 30.
20 lịch chạy thường gặp
| Biểu thức | Ý nghĩa |
|---|---|
* * * * * |
Mỗi phút |
*/5 * * * * |
Mỗi 5 phút |
*/15 * * * * |
Mỗi 15 phút |
0 * * * * |
Mỗi giờ, vào phút 0 |
30 * * * * |
Mỗi giờ vào phút 30 |
0 */2 * * * |
Mỗi 2 giờ |
0 0 * * * |
Hằng ngày lúc 0 giờ |
0 2 * * * |
Hằng ngày lúc 02:00 (hợp để backup) |
0 9 * * 1-5 |
Thứ Hai đến thứ Sáu lúc 09:00 |
*/15 9-17 * * 1-5 |
Mỗi 15 phút trong giờ hành chính các ngày thường |
0 18 * * 5 |
Thứ Sáu hằng tuần lúc 18:00 |
0 0 * * 0 |
Chủ nhật hằng tuần lúc 0 giờ |
0 0 * * 6,0 |
Thứ Bảy và Chủ nhật lúc 0 giờ |
0 0 1 * * |
Ngày đầu tiên mỗi tháng |
0 0 15 * * |
Ngày 15 mỗi tháng |
0 0 1 1 * |
Mỗi năm một lần, ngày 1/1 |
0 0 1 */3 * |
Ngày đầu mỗi quý |
0 8 1-7 * 1 |
Cẩn thận! Xem phần ngày trong tháng bên dưới |
5 4 * * sun |
Chủ nhật lúc 04:05 |
@daily |
Macro tương đương 0 0 * * * |
Nhiều bản cài đặt còn hỗ trợ các macro @yearly, @monthly, @weekly, @daily, @hourly, và Vixie cron có thêm @reboot.
Để kiểm tra một biểu thức bất kỳ, hãy dán vào công cụ Phân tích biểu thức Cron. Công cụ giải thích từng trường bằng ngôn ngữ dễ hiểu và liệt kê 10 lần chạy tiếp theo theo giờ địa phương hoặc UTC.
Khi đặt cả hai trường ngày: quy tắc HOẶC
Đây là quy tắc bị hiểu sai nhiều nhất trong cron. Khi cả hai trường ngày trong tháng và thứ trong tuần đều bị giới hạn (không trường nào là *), cron cổ điển sẽ chạy khi một trong hai khớp, chứ không phải cả hai.
0 8 1-7 * 1
Nhiều người đọc là "08:00 vào thứ Hai đầu tiên của tháng". Thực tế nó chạy lúc 08:00 các ngày từ 1 đến 7 mỗi tháng, và thêm mọi ngày thứ Hai, tức khoảng 11 lần mỗi tháng thay vì một lần.
Muốn chỉ chạy vào thứ Hai đầu tiên, hãy kiểm tra thứ ngay trong lệnh:
0 8 1-7 * * [ "$(date +\%u)" = 1 ] && /path/to/job.sh
(Để ý dấu % được escape: trong crontab, % không escape sẽ bị hiểu là xuống dòng.)
Múi giờ
Cron tính theo múi giờ của máy hoặc dịch vụ chạy nó, thường không phải giờ địa phương của bạn:
- Cron trên Linux dùng múi giờ hệ thống (máy chủ cloud thường là UTC).
- Lịch của GitHub Actions luôn chạy theo UTC.
- CronJob của Kubernetes dùng múi giờ của controller, trừ khi bạn đặt
spec.timeZone(ví dụAsia/Ho_Chi_Minh). - Ở những nơi có giờ mùa hè (DST), job có thể chạy hai lần hoặc bị bỏ qua vào thời điểm chuyển giờ.
Nếu job cần chạy lúc 09:00 giờ Việt Nam (UTC+7) trên máy chủ UTC, biểu thức phải là 0 2 * * *. Công cụ chuyển đổi Unix Timestamp rất tiện để kiểm tra lại độ lệch múi giờ.
Những cạm bẫy khác
- Bước nhảy bắt đầu lại mỗi giờ/ngày.
*/7 * * * *chạy ở phút 0, 7, 14 … 56 rồi lại phút 0. Khoảng cách giữa 56 và 0 chỉ còn 4 phút. - Ngày không tồn tại bị bỏ qua.
0 0 31 * *chỉ chạy ở tháng có 31 ngày, còn0 0 29 2 *chỉ chạy vào năm nhuận. - Chạy chồng lên nhau. Nếu job chạy lâu hơn chu kỳ, hai bản có thể chạy cùng lúc. Hãy dùng khóa (
flock) hoặcconcurrencyPolicy: Forbidtrong Kubernetes. - Môi trường tối giản. Cron chạy với
PATHrất ngắn và không nạp shell profile. Hãy dùng đường dẫn tuyệt đối và ghi log:>> /var/log/job.log 2>&1. - Biến thể 6 trường. Quartz (Java) và một số thư viện thêm trường giây ở đầu và dùng
?cho "không chỉ định". Luôn kiểm tra nền tảng của bạn dùng phương ngữ nào.
Kết luận
Cú pháp cron ngắn gọn nhưng mạnh mẽ một khi bạn nắm được 5 trường và 4 ký tự đặc biệt. Hãy nhớ quy tắc HOẶC giữa ngày trong tháng và thứ trong tuần, luôn xác nhận múi giờ, và thử biểu thức trước khi triển khai. Công cụ Phân tích biểu thức Cron miễn phí cho bạn biết chính xác khi nào lịch sẽ chạy, không cần đăng ký và không gửi dữ liệu ra khỏi trình duyệt.
Tác giả
Nguyễn Thành Nam
Full-Stack Engineer · Backend & Platform
Kỹ sư full-stack với hơn 9 năm kinh nghiệm xây dựng API và nền tảng lưu lượng lớn bằng Go, NestJS, PHP (Laravel, Phalcon) và Node.js. Chuyên về thiết kế API GraphQL, hệ thống thời gian thực và tối ưu hiệu năng; xây dựng NICETOOL.dev cho cộng đồng lập trình viên.