TIP #25: KHẮC PHỤC CRONJOB KHÔNG CHẠY

06/05/2020

CRONJOB KHÔNG CHẠY

Khi sử dụng cronjob, ta thường gặp tình trạng cronjob setup đúng nhưng không chạy. Một trong những nguyên nhân thường gặp là sự khác biệt giữa biến môi trường $PATH khi login vào terminal và khi chạy cronjob.
Mặc định, khi chạy cronjob, biến $PATH của tất cả user sẽ được set về

/usr/bin:/bin

Trong khi đó, nếu login terminal thì biến $PATH lại đa dạng hơn rất nhiều:

[[email protected] ~]# echo $PATH
/usr/local/openresty/bin:/usr/local/openresty/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

Do đó, rất nhiều trường hợp lệnh chạy ở terminal bình thường nhưng khi set cronjob thì không chạy được. Nguyên nhân là lệnh không nằm ở đường dẫn “/usr/bin” hoặc “/bin”. Vì là biến môi trường, điều này ảnh đến cả những lệnh được sử dụng trong script bash shell.

Ví dụ 1

  • Login SSH bằng user root và chạy lệnh:
# Lấy PID của process httpd
[[email protected] ~]# pidof httpd
30772 30111 30110 30109 30108 30107 17540 5842 1165
  • Ở terminal, lệnh này hoạt động bình thường. Ta setup 1 cronjob cho user root cho lệnh trên chạy định kỳ
 * * * * * pidof httpd >> /tmp/test.txt
  • Theo dõi file /tmp/test.txt, ta sẽ thấy kết quả không được update. Kiểm tra /var/log/cron cho thấy cron đã được chạy:
/var/log/cron cho thấy cron đã được chạy
[[email protected] ~]# cat /tmp/test.txt 
[[email protected] ~]# 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 thì thấy nội dung như sau:

Câu hỏi: Vì sao bước này mình lại đi kiểm tra mail của user root để xác định nguyên nhân cron không chạy?

Ví dụ 2

  • 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 cronjob và kết quả của lệnh pidof httpd vào file /tmp/test.txt.
  • Setup cronjob sử dụng đường dẫn tuyệt đối đến file “/root/test.sh”
 * * * * * /root/test.sh
  • Kết quả
  • Rõ ràng, biến môi trường có ảnh hưởng đến các lệnh nằm trong script được gọi bởi cronjob

KHẮC PHỤC

Nguyên nhân chính của tình trạng trên là do sự khác nhau của biến $PATH khi chạy trực tiếp trên terminal và biến $PATH khi được thực thi bởi cronjob. Để khắc phục, ta có thể dùng một trong 2 cách sau:

  • Sử dụng đường dẫn tuyệt đối khi chạy cron: bỏ qua sự tham gia của biến $PATH khi xác định vị trí lệnh cần chạy.
  • Khai báo lại biến $PATH khi chạy cron của user như sau:
[[email protected] ~]# crontab -l
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/home/blog
* * * * * /root/test.sh

Lưu ý: sử dụng “crontab -e” và khai báo lại biến $PATH như trên theo nhu cầu. Khi search trên mạng, sẽ có nhiều bài hướng dẫn các bạn chỉnh sửa file /etc/crontab. Tuy nhiên, đó không phải là cách làm đúng. File /etc/crontab không phải là file cấu hình cho dịch vụ cron. Đây là file system wide cronjob, việc chỉnh sửa biến $PATH trong file /etc/crontab sẽ không giải quyết được vấn đề.

Hãy tham gia vào Group Chat Telegram của nhóm để trao đổi và học hỏi kinh nghiệm với các thành viên khác nhé!