คำตอบสั้น ๆ: ใช้ Healthchecks เฝ้างาน cron และ systemd timer แบบ Dead man's switch ส่ง ping เมื่องานเริ่มและจบพร้อม Log เตือนเมื่อ Backup ไม่ทำงาน หรือติดตั้งเองด้วย Docker
คู่มือนี้อธิบาย Healthchecks ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
Healthchecks คือระบบเฝ้างานตั้งเวลาแบบ Dead man's switch หลักการคือให้งาน cron หรือ systemd timer ส่งสัญญาณ (ping) ไปหา Healthchecks ทุกครั้งที่ทำงานเสร็จ ถ้าสัญญาณไม่มาภายในรอบที่กำหนดรวมกับเวลาผ่อนผัน (Grace Time) ระบบจะส่งอีเมลเตือน ต่างจากการดู Log ที่ต้องมีคนเปิดดู เพราะความผิดปกติที่อันตรายที่สุดของงาน Backup คือการไม่ทำงานเลยโดยไม่มี Error ให้เห็น Healthchecks เป็นโอเพนซอร์ส ใช้ได้ทั้งบริการ Healthchecks.io และติดตั้งเองด้วย Docker
คู่มือนี้เหมาะกับผู้ดูแล Linux Server ที่มีงาน Backup, งานซิงก์ไฟล์ หรือสคริปต์รายคืนที่ต้องรู้ทันทีเมื่อไม่ทำงาน เมื่อทำครบ คุณจะมี Check หนึ่งตัวต่อหนึ่งงาน ตั้งรอบเวลาตรงกับ crontab ส่งสัญญาณเริ่มงาน สำเร็จ และล้มเหลวพร้อม Log ท้ายงาน ใช้ได้กับทั้ง cron และ systemd timer รับอีเมลเตือนที่ทดสอบแล้ว และถ้าต้องการ ติดตั้ง Healthchecks ไว้บนเซิร์ฟเวอร์ของตัวเอง
สิ่งที่ต้องเตรียม
- Linux Server ที่มีงานตั้งเวลาอยู่แล้ว เช่น สคริปต์สำรองข้อมูลด้วย restic และสิทธิ์
sudo curlและเซิร์ฟเวอร์ออกอินเทอร์เน็ตทาง HTTPS (พอร์ต 443) ได้- บัญชี Healthchecks.io แพ็กเกจ Hobbyist ไม่มีค่าใช้จ่าย เฝ้าได้ 20 งานตามหน้า Pricing ของผู้ให้บริการ หรือเซิร์ฟเวอร์อีกเครื่องที่ติดตั้ง Docker ถ้าจะใช้ Healthchecks แบบติดตั้งเอง
- เวลารันของแต่ละงานและเวลาที่งานใช้ตามปกติ เช่น Backup เริ่ม 02:30 ใช้เวลาราว 40 นาที
- อีเมลหรือช่องทางแจ้งเตือนที่มีคนเปิดอ่านจริงทุกวัน
ขั้นตอนที่ 1: สร้าง Check ใน Healthchecks ให้ตรงกับรอบงาน
ล็อกอิน Healthchecks.io แล้วคลิก Add Check ตั้งชื่อที่บอกเครื่องและงาน เช่น web-01 restic nightly ใส่ Tag ตามเครื่องหรือระบบเพื่อกรองดูภายหลัง จากนั้นตั้งตารางเวลาได้สองแบบ
- Simple: กำหนด Period เป็นระยะห่างระหว่างสัญญาณ เช่น 1 day และ Grace Time คือเวลาที่ยอมให้สายก่อนแจ้งเตือน
- Cron: ใส่ Cron Expression ตัวเดียวกับใน crontab เช่น
30 2 * * *และเลือก Server's Time Zone ให้ตรงกับเวลาของเครื่อง ถ้าเครื่องตั้งเป็นเวลาไทยให้เลือกAsia/Bangkokตรวจได้ด้วยtimedatectl
ตั้ง Grace Time ให้ยาวกว่าเวลาที่งานใช้ตามปกติพอสมควร เช่น งานใช้ 40 นาที ตั้ง 2 ชั่วโมง จะได้ไม่แจ้งเตือนผิดในคืนที่ข้อมูลเยอะ หลังบันทึก Healthchecks จะแสดง Ping URL รูปแบบ https://hc-ping.com/<uuid> คัดลอกเก็บไว้ URL นี้เป็นความลับระดับหนึ่ง ใครมี URL ก็ส่งสัญญาณแทนงานจริงได้ ความหมายของ Period และ Grace Time ดูได้ใน เอกสาร Configuring checks
ขั้นตอนที่ 2: เพิ่มสัญญาณ Healthchecks ในงาน cron
แบบง่ายที่สุดคือต่อท้ายคำสั่งใน crontab ด้วย && สัญญาณจะส่งเฉพาะเมื่องานจบด้วยสถานะสำเร็จ ถ้างานล้มหรือไม่ได้รัน Healthchecks จะไม่ได้รับสัญญาณและแจ้งเตือนเมื่อพ้น Grace Time (พื้นฐาน crontab ดูใน คู่มือตั้ง Cronjob)
30 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/your-uuid-here
ตัวเลือก -m 10 จำกัดเวลาต่อครั้ง 10 วินาที --retry 5 ลองใหม่เมื่อเครือข่ายสะดุด และ -fsS ให้ curl เงียบยกเว้นเมื่อมี Error ตามคำแนะนำใน เอกสาร Healthchecks สำหรับ Shell
สำหรับงานสำคัญ แนะนำสคริปต์ครอบที่ส่งสัญญาณเริ่มงาน ส่งรหัสผลลัพธ์ และแนบ Log ท้ายงานไปด้วย Healthchecks จะคำนวณเวลาที่งานใช้ แจ้งเตือนทันทีเมื่องานจบด้วยรหัสที่ไม่ใช่ 0 และแสดง Log ให้ดูในหน้า Check โดยไม่ต้อง SSH เข้าเครื่อง
#!/bin/bash
# /usr/local/bin/backup-with-ping.sh
URL="https://hc-ping.com/your-uuid-here"
LOG=/var/log/backup-last.log
curl -fsS -m 10 --retry 5 -o /dev/null "$URL/start"
/usr/local/bin/backup.sh > "$LOG" 2>&1
rc=$?
tail -c 10000 "$LOG" | curl -fsS -m 10 --retry 5 -o /dev/null --data-binary @- "$URL/$rc"
exit $rc
sudo chmod 700 /usr/local/bin/backup-with-ping.sh
sudo crontab -e
# แทนบรรทัดเดิมด้วย
30 2 * * * /usr/local/bin/backup-with-ping.sh
ปลายทาง /start บอกว่างานเริ่มแล้ว ส่วน /$rc ส่งรหัสออกของงาน Healthchecks ถือว่า 0 คือสำเร็จ ค่าอื่นคือล้มเหลว ถ้าสคริปต์ Backup ใช้ไปป์ ให้ใส่ set -o pipefail ไว้ใน backup.sh ด้วย ไม่เช่นนั้นรหัสออกจะมาจากคำสั่งสุดท้ายในไปป์เท่านั้น
ขั้นตอนที่ 3: ใช้ Healthchecks กับ systemd timer
ถ้างานรันด้วย systemd timer ตาม คู่มือ systemd Timer ให้ส่งสัญญาณเริ่มด้วย ExecStartPre และรายงานผลด้วย ExecStopPost ซึ่ง systemd ส่งตัวแปร $SERVICE_RESULT ให้ (ค่าเป็น success เมื่องานสำเร็จ) วิธีนี้ครอบคลุมกรณีงานถูก kill หรือหมดเวลาด้วย ซึ่งการต่อท้ายด้วย && จับไม่ได้
#!/bin/sh
# /usr/local/bin/hc-report.sh
URL="https://hc-ping.com/your-uuid-here"
if [ "$SERVICE_RESULT" = "success" ]; then
curl -fsS -m 10 --retry 5 -o /dev/null "$URL"
else
curl -fsS -m 10 --retry 5 -o /dev/null "$URL/fail"
fi
# /etc/systemd/system/offsite-backup.service (เพิ่มสองบรรทัดใต้ [Service])
[Service]
Type=oneshot
ExecStartPre=-/usr/bin/curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/your-uuid-here/start
ExecStart=/usr/local/bin/offsite-backup.sh
ExecStopPost=/usr/local/bin/hc-report.sh
sudo chmod 755 /usr/local/bin/hc-report.sh
sudo systemctl daemon-reload
sudo systemctl start offsite-backup.service
เครื่องหมาย - หน้า /usr/bin/curl ทำให้งานหลักยังรันต่อแม้ส่งสัญญาณเริ่มไม่สำเร็จ เพราะการ Backup สำคัญกว่าสัญญาณ