Mục lục
Điều nguy hiểm ở một cron job hỏng là chẳng có gì xảy ra cả. Không trang báo lỗi, không sập ứng dụng, không có người dùng nổi giận — chỉ có một bản sao lưu đã lặng lẽ ngừng chạy từ ba tuần trước, một báo cáo không bao giờ được gửi đi, hoặc một script dọn dẹp để ổ đĩa đầy dần cho tới khi production đổ sập.
Bản thân cron không có cơ chế cảnh báo nào. Nếu một job thoát ra với lỗi, cron chỉ nhún vai. Nếu cả máy chủ đang chết vào đúng giờ hẹn, job đơn giản là không chạy, và chẳng còn dấu vết nào để báo cho bạn biết. Trường hợp thứ hai này chính là thứ mà hầu hết các thiết lập giám sát bỏ sót.
Bài viết này trình bày ba cách để bắt được cả hai kiểu thất bại, và cách khiến cảnh báo trở nên không thể bỏ lỡ bằng việc leo thang nó thành một cuộc gọi thật với Echobell.
Cách 1: cảnh báo khi thất bại bằng hook theo mã thoát
Cách đơn giản nhất: kích hoạt một webhook mỗi khi job thoát ra với trạng thái khác 0.
Trước tiên, hãy tạo một kênh trong Echobell và sao chép webhook URL của nó. Sau đó bọc lệnh cron của bạn lại:
0 3 * * * /opt/scripts/backup.sh || curl -s "https://hook.echobell.one/t/<channel-token>?title=Backup+failed&host=$(hostname)"
Nếu backup.sh chạy thành công, không có gì xảy ra. Nếu nó thất bại, Echobell gửi cảnh báo tới điện thoại của bạn chỉ trong vài giây. Các tham số truy vấn trở thành biến mẫu, nên thông báo của bạn có thể nói chính xác máy nào và job nào đã hỏng.
Với những script dài hơn, một trap sẽ cho bạn nhiều bối cảnh hơn:
#!/usr/bin/env bash
set -euo pipefail
notify_failure() {
curl -s -X POST "https://hook.echobell.one/t/<channel-token>" \
-H "Content-Type: application/json" \
-d "{\"job\":\"nightly-backup\",\"host\":\"$(hostname)\",\"line\":\"$1\"}"
}
trap 'notify_failure $LINENO' ERR
# ... phần logic của job ...
Hạn chế: cách này chỉ hoạt động khi script thật sự chạy và thất bại. Nếu máy chủ chết, cron bị cấu hình sai, hoặc ai đó đã comment dòng lệnh lại trong một lần gỡ lỗi, thì sẽ không có cảnh báo nào được kích hoạt. Đó là lý do bạn cũng cần cách 2.
Cách 2: dead man's switch cho những lần chạy bị bỏ lỡ
Dead man's switch đảo ngược logic: job gửi ping tới một bộ giám sát khi thành công, và bộ giám sát cảnh báo bạn khi ping không đến đúng lịch. Cách này bắt được mọi kiểu thất bại — lỗi, treo, máy chủ chết, cho tới dòng crontab bị xóa.
Hai lựa chọn phổ biến có thể tự vận hành và ghép rất tốt với Echobell:
- Healthchecks.io được tạo ra đúng cho việc này. Hãy tạo một check với lịch cron và khoảng ân hạn của bạn, rồi thêm
&& curl -s https://hc-ping.com/YOUR_UUIDvào cuối dòng cron. Khi một ping đến trễ, Healthchecks gửi webhook — hãy trỏ nó tới kênh Echobell của bạn để biến một bản sao lưu bị bỏ lỡ thành tiếng chuông điện thoại. - Uptime Kuma có loại monitor "Push" hoạt động theo cùng nguyên tắc: job của bạn gọi một push URL, và Uptime Kuma cảnh báo qua các tích hợp thông báo của nó khi nhịp tim ngừng đến.
Trong cả hai trường hợp, luồng hoạt động là: cron job → ping thành công → bộ giám sát nhận ra sự im lặng → webhook tới Echobell → thông báo đẩy hoặc cuộc gọi.
Cách 3: kiểm tra theo khung thời gian cho các job có xuất dữ liệu
Có những job nên được kiểm chứng qua kết quả đầu ra thay vì mã thoát. Nếu ETL hằng đêm của bạn phải chèn xong dữ liệu trước 4 giờ sáng, một job kiểm tra nhỏ có thể đếm số dòng và gọi webhook Echobell khi con số trông không ổn.
Điều kiện của Echobell giúp ích ở đây: bạn có thể gửi một webhook trạng thái sau mỗi lần chạy và để kênh tự quyết định khi nào cần thông báo. Một điều kiện như status != "ok" giữ im lặng cho những lần chạy thành công, còn các biến thời gian UTC có sẵn cho phép bạn giới hạn cảnh báo vào đúng khung giờ mà job lẽ ra đã phải hoàn tất.
Làm cho cảnh báo không thể bỏ lỡ
Phát hiện mới chỉ là một nửa vấn đề. Một cảnh báo sao lưu thất bại rơi xuống dưới dạng banner im lặng lúc 3 giờ sáng thì về mặt tác dụng không khác gì không có cảnh báo.
Echobell cho phép mỗi kênh chọn một mức độ khẩn cấp:
- Thông thường — thông báo đẩy tiêu chuẩn, phù hợp với các job mang tính thông tin
- Khẩn cấp — xuyên qua chế độ Tập trung của iOS, hợp với những job cần ai đó xem sớm
- Cuộc gọi — điện thoại của bạn đổ chuông như một cuộc gọi thật cho tới khi bạn để ý
Với những job mà thất bại trong im lặng gây thiệt hại tiền thật — sao lưu cơ sở dữ liệu, chạy hóa đơn, gia hạn chứng chỉ — hãy đặt kênh ở mức Cuộc gọi. Khác biệt giữa "thấy lúc 3 giờ sáng" và "thấy lúc 9 giờ sáng" đúng bằng khác biệt mà một cảnh báo bằng cuộc gọi tạo ra.
Nếu có nhiều người cùng chịu trách nhiệm cho một job, hãy chia sẻ liên kết đăng ký của kênh với cả nhóm; ai đăng ký cũng nhận được cùng một cảnh báo vào cùng một thời điểm.
Bạn nên dùng cách nào?
- Hook theo mã thoát: thiết lập trong năm phút, bắt được các thất bại lộ rõ. Hãy bắt đầu từ đây.
- Dead man's switch: bắt được cả những lần chạy bị bỏ lỡ và bị treo. Hãy thêm nó cho mọi job mà bạn thật sự không muốn bỏ sót.
- Kiểm tra dữ liệu theo khung thời gian: dành cho những pipeline mà "chạy xong nhưng ra dữ liệu rác" là rủi ro có thật.
Chúng bổ trợ cho nhau rất tốt: hook theo mã thoát cho bạn biết một job đã hỏng và vì sao, còn dead man's switch bảo đảm bạn vẫn nghe được về những thất bại chưa kịp tự báo cáo.
Hãy thiết lập cảnh báo cron đầu tiên của bạn chỉ trong vài phút: tải Echobell, tạo một kênh, và thêm một lệnh curl vào crontab. Lần tới khi một tác vụ định kỳ chết lúc 3 giờ sáng, điện thoại của bạn sẽ đổ chuông — và bản sao lưu bạn cần khôi phục vào quý sau sẽ thật sự tồn tại.