nicetool.dev logo
#cron#devops#linux

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ờ.

5 phút đọc

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

  1. 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.
  2. Ngày không tồn tại bị bỏ qua. 0 0 31 * * chỉ chạy ở tháng có 31 ngày, còn 0 0 29 2 * chỉ chạy vào năm nhuận.
  3. 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ặc concurrencyPolicy: Forbid trong Kubernetes.
  4. Môi trường tối giản. Cron chạy với PATH rấ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.
  5. 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.

Tự thử ngay

Bài viết liên quan