Cron job là công cụ tự động hóa hữu ích trên Linux, giúp bạn lên lịch thực thi các tác vụ lặp lại nhanh chóng, tiết kiệm thời gian. Tuy nhiên, khi một cron job không chạy, đa số nguyên nhân đều xuất phát từ việc môi trường thực thi của cron có sự khác biệt so với môi trường shell khi bạn đăng nhập trực tiếp. Trong bài viết này, mình sẽ cùng bạn tìm hiểu về nguyên nhân và cách khắc phục cron job không chạy hiệu quả.
Những điểm chính
- Định nghĩa cron job: Là tác vụ được định nghĩa trong Crontab, cho phép hệ thống tự động thực thi lệnh hoặc kịch bản theo lịch trình định sẵn, không cần can thiệp thủ công.
- Cấu trúc và cú pháp: Mỗi cron job là một dòng gồm Trường thời gian (Phút, giờ, ngày, tháng, thứ) và Lệnh/Kịch bản, sử dụng ký tự đặc biệt (*, ,, -, /) để linh hoạt lịch trình.
- Nguyên nhân cron job không chạy: Môi trường hoạt động khác biệt (Thiếu $PATH), thiếu quyền thực thi script hoặc sử dụng đường dẫn tương đối.
- Ví dụ lệnh không chạy: Lệnh
pidof httpd
không cập nhật kết quả vào file/tmp/test.txt
dù cron chạy bình thường, do thiếu biến môi trường và quyền thực thi. - Khắc phục cronjob không chạy: Sử dụng đường dẫn tuyệt đối hoặc khai báo biến PATH trong crontab.
- Các bước kiểm tra toàn diện: Kiểm tra dịch vụ Cron, cú pháp Crontab, log hệ thống, quyền thực thi script, chuyển hướng output và xử lý ký tự đặc biệt %.
- Câu hỏi thường gặp: Giải đáp các câu hỏi thường gặp liên quan đến cron job.
Cron job là gì?
Định nghĩa
Cron job là một lệnh được sử dụng để lập lịch cho các tác vụ tự động trên các hệ điều hành, cho phép người dùng và quản trị viên hệ thống tự động hóa các công việc cần thực hiện lặp lại, chẳng hạn như sao lưu dữ liệu, dọn dẹp tệp tin tạm, hoặc gửi báo cáo định kỳ. Hoạt động như một tiến trình nền, Cron sẽ kiểm tra tệp cấu hình (crontab) để thực thi các lệnh vào đúng thời điểm đã được chỉ định, giúp giải phóng con người khỏi các công việc thủ công và đảm bảo tính nhất quán.

Cấu trúc
Mỗi cron job được định nghĩa trên một dòng duy nhất trong file Crontab. Cấu trúc của dòng này bao gồm hai phần chính được phân tách bởi khoảng trắng.
[Trường Thời gian] [Lệnh hoặc Kịch bản cần thực thi]
- Phần đầu tiên là trường thời gian, bao gồm năm trường con để xác định lịch trình thực thi.
- Phần thứ hai là lệnh hoặc đường dẫn tuyệt đối đến một kịch bản mà hệ thống sẽ chạy khi thời gian hiện tại khớp với lịch trình đã định.
Cú pháp
Cú pháp của cron job tập trung chủ yếu vào cách định nghĩa trường thời gian, bao gồm năm trường con, mỗi trường đại diện cho một đơn vị thời gian khác nhau, theo thứ tự sau:
phút giờ ngày tháng thứ_trong_tuần

- Trường thứ nhất: Phút (Giá trị hợp lệ: 0 – 59).
- Trường thứ hai: Giờ (Giá trị hợp lệ: 0 – 23).
- Trường thứ ba: Ngày trong tháng (Giá trị hợp lệ: 1 – 31).
- Trường thứ tư: Tháng (Giá trị hợp lệ: 1 – 12 hoặc tên viết tắt như Jan, Feb).
- Trường thứ năm: Thứ trong tuần (Giá trị hợp lệ: 0 – 7, với cả 0 và 7 đều đại diện cho Chủ Nhật hoặc tên viết tắt như Sun, Mon).
Ngoài các giá trị số, cú pháp của cron job còn sử dụng các ký tự đặc biệt để tạo ra các lịch trình linh hoạt:
*
(Dấu hoa thị): Đại diện cho tất cả các giá trị có thể có của một trường. Ví dụ,*
trong trường “giờ” có nghĩa là “mỗi giờ”.,
(Dấu phẩy): Dùng để liệt kê nhiều giá trị riêng biệt. Ví dụ,0,15,30,45
trong trường “phút” có nghĩa là tác vụ sẽ chạy vào phút thứ 0, 15, 30 và 45.-
(Dấu gạch nối): Dùng để xác định một khoảng giá trị liên tiếp. Ví dụ,1-5
trong trường “thứ trong tuần” có nghĩa là tác vụ sẽ chạy từ thứ Hai đến thứ Sáu./
(Dấu gạch chéo): Dùng để xác định các bước nhảy (Step). Ví dụ,*/15
trong trường “phút” có nghĩa là “mỗi 15 phút”, tương đương với0,15,30,45
.
Vì sao cron job không chạy?
Một cron job không chạy thường do ba nguyên nhân chính sau:
- Môi trường hoạt động khác biệt: Cron job chạy trong một môi trường hệ thống rất đơn giản, không đầy đủ như khi bạn tự đăng nhập vào máy chủ. Đặc biệt, nhiều biến hệ thống quan trọng như
$PATH
thường bị thiếu, khiến cron không nhận diện được các lệnh mà bạn vẫn chạy bình thường trong terminal. - Thiếu quyền thực thi: Nếu cron job gọi một file script, file này bắt buộc phải được cấp quyền thực thi. Dù cron đã được kích hoạt đúng thời điểm, hệ thống vẫn sẽ từ chối nếu script không đảm bảo quyền này.
- Sử dụng đường dẫn tương đối: cron job không biết thư mục làm việc hiện tại của bạn là ở đâu. Nếu bạn sử dụng các đường dẫn tương đối (Ví dụ:
data/file.txt
thay vì/home/user/data/file.txt
), cron sẽ không thể tìm thấy các tệp hoặc kịch bản cần thiết để thực thi.

Ví dụ lệnh ở cron job không chạy
Đầu tiên, mình login SSH bằng user root và chạy lệnh:
# Lấy PID của process httpd
[root@quantrilinux.vn ~]# pidof httpd
30772 30111 30110 30109 30108 30107 17540 5842 1165
Ở terminal, lệnh hoạt động bình thường, mình setup một cron job cho user root cho lệnh trên chạy định kỳ:
* * * * * pidof httpd >> /tmp/test.txt
Theo dõi file /tmp/test.txt
, mình thấy kết quả không được update, khi kiểm tra /var/log/cron
cho thấy cron đã được chạy:
[root@quantrilinux.vn ~]# cat /tmp/test.txt
[root@quantrilinux.vn ~]# tail /var/log/cron
May 6 12:03:01 blog CROND[30404]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:04:01 blog CROND[30494]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:05:01 blog CROND[30568]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:06:01 blog CROND[30648]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:07:01 blog CROND[30719]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:08:01 blog CROND[30801]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:09:01 blog CROND[30895]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:10:01 blog CROND[30977]: (root) CMD (pidof httpd >> /tmp/test.txt)
May 6 12:10:46 blog crontab[31031]: (root) LIST (root)
May 6 12:11:01 blog CROND[31049]: (root) CMD (pidof httpd >> /tmp/test.txt)
Kiểm tra mail của user root, mình thấy xuất hiện thấy nội dung như sau:

Ví dụ về script bash shell không chạy ở cron job dù chạy bình thường trên terminal:
Tương tự ví dụ 1, lúc này mình sẽ đưa lệnh pidof
vào file Bash Shell, tạo file /root/test.sh
có nội dung như sau:
/#!/bin/bash
echo "----------"
echo $PATH >> /tmp/test.txt
pidof httpd >> /tmp/test.txt
File có nhiệm vụ in ra biến môi trường khi chạy cron job và kết quả của lệnh pidof httpd
vào file /tmp/test.txt
. Sau đó, mình setup cron job sử dụng đường dẫn tuyệt đối đến file /root/test.sh:
* * * * * /root/test.sh

Kết quả cho thấy biến môi trường có ảnh hưởng đến các lệnh nằm trong script được gọi bởi cron job.
Cách khắc phục cron job không chạy
Cách 1: Sử dụng đường dẫn tuyệt đối
Sử dụng đường dẫn tuyệt đối là cách an toàn nhất, thay vì gọi một lệnh, bạn hãy chỉ định đường dẫn đầy đủ. Để tìm đường dẫn của một lệnh, bạn dùng lệnh which
:
which mysqldump
# Output ví dụ: /usr/bin/mysqldump
Sau đó, bạn sử dụng đường dẫn đầy đủ này trong script hoặc trực tiếp trong crontab của bạn.
Cách 2: Khai báo biến PATH trong Crontab
Bạn có thể chỉ định biến PATH ngay ở đầu file crontab để áp dụng cho tất cả các job bên dưới. Sau đó, bạn mở crontab bằng lệnh crontab -e
và thêm vào dòng sau ở trên cùng:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Các cronjob của bạn đặt ở dưới đây
*/5 * * * * /path/to/your/script.sh
Lưu ý
Các bước kiểm tra cron job toàn diện khác
Ngoài vấn đề về PATH, còn nhiều nguyên nhân khác có thể khiến cron job không chạy. Bạn hãy kiểm tra lần lượt các mục sau:
1. Kiểm tra tình trạng hoạt động của dịch vụ Cron (crond)
Bạn kiểm tra trạng thái hoạt động của dịch vụ Cron bằng lệnh sau:
# Dành cho Debian/Ubuntu
sudo systemctl status cron
# Dành cho CentOS/RHEL/Fedora
sudo systemctl status crond
Nếu dịch vụ không chạy, bạn hãy khởi động bằng lệnh sau:
sudo systemctl start cron (hoặc crond).
2. Kiểm tra cú pháp Crontab
Một dấu cách thừa hay một ký tự sai cũng có thể làm ảnh hưởng đến toàn bộ file crontab. Vì vậy, bạn hãy kiểm tra kỹ 5 trường thời gian là (phút) (giờ) (ngày) (tháng) (thứ). Ngoài ra, bạn cũng có thể sử dụng các công cụ online như Crontab Guru để xác thực cú pháp của bạn.
3. Kiểm tra Log hệ thống
Các tác vụ do cron thực hiện sẽ được lưu lại trong các file nhật ký của hệ thống. Để kiểm tra log hệ thống, bạn thực hiện lệnh sau:
# Dành cho Debian/Ubuntu
sudo grep CRON /var/log/syslog
# Dành cho CentOS/RHEL/Fedora
sudo grep CRON /var/log/cron
Log sẽ cho bạn biết cron đã cố gắng chạy lệnh nào và vào lúc nào.
4. Quyền thực thi của Script
Nếu cron job của bạn gọi một file script (Ví dụ: backup.sh
), file đó phải có quyền thực thi. Bạn có thể gán quyền thực thi bằng lệnh sau:
chmod +x /path/to/your/script.sh
5. Chuyển hướng Output để ghi lại lỗi
Chuyển hướng Output để ghi lại lỗi là cách debug hiệu quả nhất, bạn hãy chuyển hướng toàn bộ output và lỗi của cron job vào một file log riêng để xem vấn đề gì đã xảy ra. Sửa lại cron job của bạn bằng lệnh sau:
* * * * * /path/to/command > /tmp/cron_job.log 2>&1
>
: Chuyển hướng output chuẩn (stdout
).2>&1
: Chuyển hướng lỗi chuẩn (stderr
) vào cùng nơi vớistdout
. Sau khi cron chạy, bạn hãy kiểm tra file/tmp/cron_job.log
để xem có thông báo lỗi nào không.
6. Xử lý ký tự đặc biệt %
Ký tự %
có ý nghĩa đặc biệt trong crontab (Coi là ký tự xuống dòng). Nếu lệnh của bạn chứa ký tự này, bạn hãy escape bằng dấu \
.
- Lỗi:
... date +%Y-%m-%d
- Sửa:
... date +\%Y-\%m-\%d
Câu hỏi thường gặp
Làm thế nào để nhận thông báo lỗi khi cron job chạy?
Bạn có thể thêm dòng sau vào đầu file crontab để nhận mail báo lỗi nếu có:
MAILTO=”email@domain.com”
Hoặc chuyển hướng stderr và stdout ra file log cụ thể:
* * * * /path/to/script.sh >> /tmp/script.log 2>&1
Cron có thể bị giới hạn bởi quyền hoặc SELinux không?
Nếu chạy cron dưới user không đủ quyền với file/script, cron job sẽ không chạy. Một số hệ điều hành bật SELinux có thể hạn chế cron thực hiện script ở thư mục không cho phép.
Vì sao cron job đã cài đặt mà lại không thực hiện?
Có một số lý do phổ biến khiến cron job không chạy:
– Cấu trúc dòng cron sai định dạng hoặc thiếu thông tin.
– Quyền thực thi của script chưa được cấp.
– Đường dẫn tệp hoặc lệnh không tuyệt đối, khiến cron không tìm thấy script.
– Biến môi trường của cron khác so với khi chạy shell thông thường.
– Cron daemon chưa được khởi động hoặc gặp sự cố.
Kết luận
Vấn đề cron job không chạy thường xuất phát từ sự khác biệt về môi trường thực thi, đặc biệt là biến $PATH
. Việc hiểu và áp dụng các giải pháp như sử dụng đường dẫn tuyệt đối hoặc khai báo PATH trong crontab là cực kỳ quan trọng. Bên cạnh đó, bằng cách kiểm tra một cách có hệ thống qua các bước bổ sung như kiểm tra log, quyền và chuyển hướng output, bạn có thể nhanh chóng chẩn đoán và khắc phục cron job không chạy một cách hiệu quả, triệt để nhất để đảm bảo các tác vụ tự động của mình luôn hoạt động ổn định.