Đọc hiểu cron expression trong 5 phút
19/07/2026
Nếu bạn từng nhìn vào một dòng như */5 * * * * và tự hỏi "cái này chạy lúc nào?", thì bài viết này dành cho bạn. Cron expression là một trong những cú pháp phổ biến nhất trong đời sống của developer, nhưng cũng dễ gây nhầm lẫn nhất. Chỉ mất 5 phút, bạn sẽ đọc hiểu được gần như mọi cron expression gặp trong thực tế.
Cron là gì và dùng ở đâu?
Cron là trình lập lịch (scheduler) chạy tác vụ theo thời gian trên các hệ thống Unix/Linux. Bạn khai báo "chạy lệnh này vào lúc nào" bằng một chuỗi ngắn gọi là cron expression. Cú pháp này đã trở thành chuẩn chung, xuất hiện ở khắp nơi ngoài crontab truyền thống:
- crontab trên Linux — lập lịch backup, dọn log, gửi báo cáo định kỳ.
- Spring Framework — annotation
@Scheduled(cron = "...")để chạy method theo lịch. - Kubernetes CronJob — trường
scheduletrong manifest để chạy Pod định kỳ. - CI/CD — GitHub Actions (
on.schedule.cron), GitLab CI pipeline schedules. - Các thư viện job — Quartz (Java), node-cron, Celery beat (Python)...
Hiểu cron một lần là dùng được ở tất cả những nơi này, chỉ cần lưu ý vài khác biệt nhỏ giữa các nền tảng mà chúng ta sẽ nói ở cuối bài.
Cấu trúc 5 trường
Cron expression chuẩn (Unix) gồm 5 trường phân tách bằng khoảng trắng, theo đúng thứ tự từ trái sang phải:
┌───────────── phút (0 - 59)
│ ┌─────────── giờ (0 - 23)
│ │ ┌───────── ngày tháng (1 - 31)
│ │ │ ┌─────── tháng (1 - 12)
│ │ │ │ ┌───── thứ tuần (0 - 6, 0 = Chủ nhật)
│ │ │ │ │
* * * * *
Ý nghĩa từng trường:
- Phút (0-59) — phút trong giờ mà tác vụ chạy.
- Giờ (0-23) — giờ trong ngày theo định dạng 24 giờ;
0là nửa đêm,23là 11 giờ tối. - Ngày trong tháng (1-31) — ngày cụ thể của tháng.
- Tháng (1-12) — tháng trong năm; nhiều hệ chấp nhận cả tên viết tắt tiếng Anh như
JAN,FEB. - Thứ trong tuần (0-6) — với
0= Chủ nhật,1= Thứ hai, ...,6= Thứ bảy. Nhiều hệ cũng cho phép tên viết tắt nhưMON,SUN.
Một tác vụ sẽ chạy khi thời điểm hiện tại khớp với tất cả các trường. Ví dụ 30 8 * * 1 nghĩa là: phút = 30, giờ = 8, mọi ngày trong tháng, mọi tháng, và thứ = Thứ hai — tức là 8h30 sáng mỗi Thứ hai.
Bốn ký tự đặc biệt cần nhớ
Sức mạnh của cron nằm ở bốn ký tự đặc biệt dùng được trong mỗi trường:
Dấu sao * — mọi giá trị
Khớp với mọi giá trị hợp lệ của trường đó. * * * * * nghĩa là "mỗi phút, mọi lúc". Đặt * ở trường phút nghĩa là không giới hạn theo phút.
Dấu phẩy , — danh sách
Liệt kê nhiều giá trị rời rạc. 0 9,12,18 * * * chạy vào 9h, 12h và 18h mỗi ngày — ba mốc giờ cụ thể.
Dấu gạch ngang - — khoảng
Chỉ định một dải giá trị liên tục. 0 9-17 * * * chạy mỗi giờ từ 9h đến 17h (9, 10, 11, ... 17). Trong trường thứ tuần, 1-5 là từ Thứ hai đến Thứ sáu.
Dấu gạch chéo / — bước nhảy
Chạy theo khoảng cách đều đặn. */15 * * * * chạy mỗi 15 phút (phút 0, 15, 30, 45). Có thể kết hợp với khoảng: 0-30/10 nghĩa là các phút 0, 10, 20, 30.
Bạn có thể trộn các ký tự này. Ví dụ */10 9-17 * * 1-5: mỗi 10 phút, trong khung giờ hành chính 9h-17h, chỉ các ngày Thứ hai đến Thứ sáu. Nếu muốn kiểm tra nhanh một biểu thức mà không cần nhẩm trong đầu, hãy dùng công cụ Cron Expression Parser để dịch ngược cron expression sang tiếng người và xem các lần chạy kế tiếp.
Lưu ý: biến thể 6 trường (giây) và thứ tự của Spring
Đây là chỗ gây nhầm lẫn nhiều nhất khi chuyển giữa các nền tảng. Ngoài chuẩn 5 trường của Unix, nhiều framework Java dùng biến thể 6 trường có thêm giây:
- Quartz Scheduler dùng 6 (hoặc 7) trường:
giây phút giờ ngày-tháng tháng thứ-tuần [năm]. Ngoài ra Quartz đánh số thứ tuần từ1(Chủ nhật) đến7(Thứ bảy) — khác hẳn Unix. - Spring (annotation
@Scheduled) dùng 6 trường theo thứ tự:giây phút giờ ngày-tháng tháng thứ-tuần.
Ví dụ trong Spring, 0 0 9 * * MON-FRI nghĩa là giây = 0, phút = 0, giờ = 9, các ngày Thứ hai đến Thứ sáu — tức 9h00 sáng ngày làm việc. Nếu bạn quen với cú pháp 5 trường của crontab và bê nguyên 0 9 * * 1-5 vào Spring, biểu thức sẽ bị hiểu sai (thiếu một trường). Luôn kiểm tra xem nền tảng bạn đang dùng cần 5 hay 6 trường trước khi viết.
Bảng ví dụ thực tế
Dưới đây là những cron expression 5 trường hay gặp nhất. Học thuộc vài dòng này là đủ dùng cho 90% trường hợp:
| Expression | Ý nghĩa |
|---|---|
* * * * * |
Mỗi phút |
*/5 * * * * |
Mỗi 5 phút |
0 * * * * |
Đầu mỗi giờ (phút 0) |
0 */2 * * * |
Mỗi 2 giờ |
0 9 * * 1-5 |
9h sáng, Thứ hai đến Thứ sáu |
30 3 * * 0 |
3h30 sáng mỗi Chủ nhật |
0 0 1 * * |
0h ngày mùng 1 hàng tháng |
0 0 * * 0 |
0h Chủ nhật hàng tuần |
15 14 1 * * |
14h15 ngày mùng 1 hàng tháng |
0 22 * * 1-5 |
22h các ngày làm việc |
0 0 1 1 * |
0h ngày 1 tháng 1 (đầu năm) |
0 9,17 * * * |
9h và 17h mỗi ngày |
Ba cái bẫy thường gặp
Ngay cả developer có kinh nghiệm cũng hay vấp phải những điểm sau:
-
Trộn ngày-trong-tháng và thứ-trong-tuần. Khi bạn đặt cả hai trường (không phải
*), phần lớn hệ cron dùng logic HOẶC chứ không phải VÀ. Ví dụ0 0 13 * 5chạy vào 0h mỗi ngày 13 hoặc mỗi Thứ sáu — không phải chỉ "Thứ sáu ngày 13". Đây là nguồn gốc của rất nhiều job chạy nhiều hơn mong đợi. Nếu chỉ cần một điều kiện, hãy để trường còn lại là*. -
Múi giờ của server. Cron chạy theo múi giờ của hệ thống nơi nó thực thi, thường là UTC trên server cloud. Một job
0 0 * * *tưởng là "nửa đêm giờ Việt Nam" nhưng thực tế có thể chạy lúc 7h sáng nếu server dùng UTC. Luôn kiểm tra timezone của server (hoặc cấu hìnhCRON_TZ/TimeZonenếu nền tảng hỗ trợ) trước khi tin vào giờ chạy. -
0và7đều là Chủ nhật. Trong nhiều bản cron (như Vixie cron trên Linux), trường thứ tuần chấp nhận cả0lẫn7cho Chủ nhật. Nhưng đừng dựa vào điều này khi viết code chạy đa nền tảng — Quartz lại đánh số1là Chủ nhật. Khi nghi ngờ, dùng tên viết tắt (SUN,MON) cho rõ ràng, hoặc kiểm chứng bằng công cụ trước khi deploy.
Tóm tắt
Cron expression về bản chất chỉ là 5 trường — phút, giờ, ngày tháng, tháng, thứ tuần — cộng với bốn ký tự đặc biệt *, ,, -, /. Nắm được từng đó là bạn đọc hiểu được hầu hết lịch chạy trong crontab, Spring, Kubernetes hay CI. Chỉ cần nhớ thêm: một số nền tảng có trường giây (6 trường), thứ tự trường của Spring/Quartz khác Unix, cẩn thận với logic HOẶC khi đặt cả ngày lẫn thứ, và luôn để ý múi giờ server.
Lần tới khi gặp một cron expression lạ, đừng nhẩm trong đầu — hãy dán vào Cron Expression Parser của DevToolHub để dịch sang tiếng người, kiểm tra tính hợp lệ và xem trước các lần chạy kế tiếp. Nhanh, chính xác, và tránh được những cái bẫy vừa kể trên.