Cron job trong Bash cho DevOps
Ở bài trước chúng ta đã quản lý biến, .env, tham số CLI và các biến đặc biệt trong Bash. Khi script đã chạy ổn định bằng tay, bước tiếp theo thường là: làm sao để nó tự chạy đúng thời điểm?
cron là công cụ kinh điển trên Linux/Unix để chạy command hoặc script theo lịch. Với DevOps, cron thường dùng cho backup định kỳ, dọn log, healthcheck, đồng bộ file, tạo report, kiểm tra chứng chỉ SSL hoặc gọi một endpoint bảo trì nhẹ.
Điểm quan trọng: cron chạy trong môi trường tối giản hơn terminal của bạn. Vì vậy script chạy đúng khi gọi tay chưa chắc chạy đúng trong cron nếu thiếu PATH, working directory, biến môi trường hoặc log rõ ràng.
Cron và crontab là gì
cron là daemon chạy nền, đọc các bảng lịch và thực thi command khi tới thời điểm phù hợp. Bảng lịch đó thường được gọi là crontab.
Một số lệnh cơ bản:
| |
Bạn có thể chỉnh crontab của user hiện tại bằng crontab -e. Trên server production, hãy cẩn thận với crontab -r vì lệnh này xóa toàn bộ lịch của user đó.
Ví dụ một dòng cron đơn giản:
| |
Dòng trên chạy script mỗi 5 phút và ghi cả stdout/stderr vào file log.
Cú pháp lịch 5 trường
Một cron job phổ biến có 5 trường thời gian, sau đó là command:
| |
Một vài ví dụ hay gặp:
| |
Cron cũng hỗ trợ danh sách, range và bước nhảy:
| |
Khi viết lịch cho production, nên thêm comment phía trên để người sau hiểu mục đích của job.
Shortcut @daily, @hourly, @reboot
Nhiều hệ thống cron hỗ trợ các shortcut giúp crontab dễ đọc hơn:
| |
@daily thường tương đương chạy một lần mỗi ngày vào nửa đêm. @reboot chạy khi cron daemon khởi động, thường dùng cho tác vụ nhẹ sau khi server boot.
Không nên lạm dụng @reboot cho service quan trọng. Với daemon dài hạn, systemd service thường phù hợp hơn vì có restart policy, dependency và log rõ ràng qua journalctl.
Viết script Bash thân thiện với cron
Script chạy từ cron nên tự chuẩn bị môi trường cần thiết thay vì phụ thuộc vào shell tương tác.
Ví dụ khung script tốt:
| |
Các điểm cần chú ý:
- Khai báo shebang rõ ràng.
- Bật
set -euo pipefailđể lỗi không bị nuốt im lặng. - Đặt
PATHtrong script hoặc trong crontab. - Dùng path tuyệt đối cho file quan trọng.
- Ghi log có timestamp.
- Không giả định cron chạy từ thư mục project.
Redirect log trong cron
Cron có thể gửi output qua mail nội bộ nếu hệ thống cấu hình mail. Trong thực tế DevOps, ghi log vào file thường dễ kiểm soát hơn.
Ví dụ redirect stdout và stderr:
| |
Ý nghĩa:
>> /var/log/check-health.log: append stdout vào file.2>&1: chuyển stderr vào cùng nơi với stdout.
Nếu muốn tách log lỗi riêng:
| |
Với job chạy thường xuyên, cần có chiến lược rotate log bằng logrotate hoặc tự giới hạn dung lượng, nếu không file log có thể đầy disk.
Kiểm tra log cron
Vị trí log cron phụ thuộc distro và cấu hình logging.
Trên nhiều hệ thống Ubuntu/Debian dùng syslog:
| |
Trên hệ thống dùng systemd journal:
| |
Một số distro dùng service tên crond thay vì cron. Nếu không chắc, kiểm tra service:
| |
Lưu ý: log cron thường chỉ cho biết cron đã gọi command hay chưa, không đảm bảo command thành công. Muốn biết script lỗi gì, bạn vẫn cần redirect output hoặc tự ghi log trong script.
Vấn đề PATH và environment trong cron
Cron không load đầy đủ .bashrc, .profile hoặc environment giống terminal của bạn. Đây là nguyên nhân phổ biến khiến script chạy tay thì đúng, nhưng vào cron lại lỗi command not found.
Ví dụ nên đặt PATH ở đầu crontab:
| |
Hoặc dùng path tuyệt đối cho command trong script:
| |
Với biến môi trường riêng của app, ưu tiên load từ file config do bạn kiểm soát:
| |
Không đặt secret trực tiếp trong crontab nếu nhiều người có quyền đọc crontab hoặc backup hệ thống. Với secret quan trọng, dùng secret manager, file quyền hạn chặt chẽ hoặc cơ chế secret của nền tảng đang dùng.
Thực hành DevOps: backup database hằng đêm
Ví dụ dưới đây minh họa script backup PostgreSQL hằng đêm. Script dùng biến môi trường từ file cấu hình, tạo thư mục backup, nén output và xóa bản backup cũ.
File /opt/scripts/backup-db.sh:
| |
File /etc/example-app/backup.env:
| |
Đặt quyền file config chặt chẽ:
| |
Thêm cron job chạy lúc 02:30 mỗi ngày:
| |
Trong môi trường thật, hãy test restore định kỳ. Backup chỉ có giá trị khi bạn biết chắc có thể khôi phục được.
Thực hành DevOps: healthcheck mỗi 5 phút
Ví dụ script kiểm tra endpoint /health, retry nhẹ rồi ghi log. Nếu endpoint vẫn lỗi, script trả exit code khác 0 để cron log lại trạng thái lỗi.
File /opt/scripts/check-health.sh:
| |
Crontab:
| |
Inline environment variable như trên phù hợp với giá trị không nhạy cảm. Nếu cần token hoặc header bí mật, hãy load từ file quyền hạn chặt chẽ hoặc secret manager thay vì đặt thẳng trong crontab.
Tránh job chạy chồng lên nhau
Nếu một job chạy lâu hơn chu kỳ cron, lần chạy mới có thể bắt đầu khi lần cũ chưa xong. Điều này nguy hiểm với backup, cleanup hoặc deploy.
Một cách phổ biến là dùng flock:
| |
flock -n sẽ không chờ lock. Nếu job cũ còn chạy, job mới thoát ngay. Với backup:
| |
Không phải hệ thống nào cũng cài sẵn flock, nhưng trên nhiều distro Linux nó nằm trong gói util-linux. Nếu môi trường của bạn không có flock, cần dùng cơ chế lock khác và xử lý stale lock cẩn thận.
Sai sót thường gặp
- Quên redirect log: Job lỗi nhưng không có output để debug.
- Phụ thuộc vào working directory: Cron không đảm bảo chạy trong thư mục project.
- Thiếu
PATH: Command nhưdocker,kubectl,node,pythoncó thể không tìm thấy. - Dùng path tương đối: File config, log, backup nên dùng path tuyệt đối.
- Không kiểm soát job chạy chồng: Backup/cleanup có thể chạy đồng thời và gây hỏng dữ liệu.
- Đặt secret trực tiếp trong crontab: Khó quản lý quyền và audit.
- Không test command trước khi lưu crontab: Nên chạy script bằng đúng user sẽ chạy cron.
Ghi chú triển khai
- Khi áp dụng vào dự án của bạn, hãy chuẩn hóa mỗi cron job theo checklist nhỏ:
- Script có shebang,
set -euo pipefailvà path tuyệt đối. - Crontab có comment mô tả mục đích job.
- Output được redirect vào log hoặc gửi về hệ thống logging.
- Job dài có lock để tránh chạy chồng.
- Secret nằm trong nơi phù hợp, không hardcode trong script public.
- Script có shebang,
- Best practices:
- Test script bằng tay với đúng user:
sudo -u <app-user> /opt/scripts/job.sh. - Ghi timestamp trong log để dễ đối chiếu sự cố.
- Đặt
PATHrõ ràng trong script hoặc crontab. - Dùng
flockcho job có thể chạy lâu. - Theo dõi dung lượng log/backup bằng
logrotatehoặc retention policy.
- Test script bằng tay với đúng user:
- Troubleshooting:
- Job không chạy? → Kiểm tra
crontab -l, cú pháp lịch, timezone và log cron. - Job chạy nhưng command lỗi? → Kiểm tra file log riêng của script.
- Chạy tay đúng nhưng cron sai? → Kiểm tra
PATH, working directory, permission và biến môi trường.
- Job không chạy? → Kiểm tra
🎯 Lời kết
Cron giúp Bash script trở thành một phần của lịch vận hành tự động: backup hằng đêm, healthcheck định kỳ, cleanup log hoặc tạo report. Nhưng để cron job đáng tin cậy, bạn cần viết script tự chủ về môi trường, dùng path tuyệt đối, ghi log rõ ràng và tránh chạy chồng khi job có thể kéo dài.
Ở bài tiếp theo, chúng ta sẽ đi vào debug script Bash: bash -x, bash -n, set -x, set -e, set -u, pipefail, trap ERR, PS4 và shellcheck để tìm lỗi nhanh hơn. 🚀
Tài liệu tham khảo
- man7.org — crontab(5) — Tham khảo cú pháp crontab, 5 trường thời gian và các biến môi trường trong cron.
- man7.org — cron(8) — Mô tả cron daemon và cách cron xử lý lịch chạy.
- man7.org — flock(1) — Tham khảo
flockđể tránh job chạy chồng. - PostgreSQL Documentation — pg_dump — Tài liệu chính thức về
pg_dumpdùng trong ví dụ backup. - curl Documentation — Tham khảo
--fail,--silent,--show-error,--max-timedùng trong ví dụ healthcheck.
