คำตอบสั้น ๆ: ตั้งค่าสำรองไฟล์จาก Linux Server ไปยังเซิร์ฟเวอร์ปลายทางด้วย rsync ผ่าน SSH Key และให้ Cronjob รันสคริปต์สำรองข้อมูลอัตโนมัติทุกวัน
คู่มือนี้อธิบาย Cronjob ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
การเก็บไฟล์สำรองไว้บนเซิร์ฟเวอร์เครื่องเดียวกับข้อมูลจริงไม่ช่วยอะไรเมื่อดิสก์เสีย เครื่องถูกลบ หรือถูกโจมตี วิธีที่ง่ายและใช้กันแพร่หลายคือใช้ rsync คัดลอกไฟล์ผ่าน SSH ไปเก็บที่เซิร์ฟเวอร์อีกเครื่อง rsync ส่งเฉพาะส่วนที่เปลี่ยนแปลง จึงเร็วและประหยัด Bandwidth หลังจากรอบแรก
คู่มือนี้เรียกเครื่องที่มีข้อมูลว่า เครื่องต้นทาง และเครื่องที่เก็บสำรองว่า เครื่องปลายทาง (ตัวอย่าง IP 203.0.113.20) ใช้ได้กับ Ubuntu, AlmaLinux และ Rocky Linux
สิ่งที่ต้องเตรียม
- สิทธิ์
sudoบนเครื่องต้นทาง และผู้ใช้สำหรับรับไฟล์บนเครื่องปลายทาง (ตัวอย่างใช้ชื่อbackup) - เครื่องต้นทางเชื่อมต่อ SSH ไปยังเครื่องปลายทางได้
- พื้นที่บนเครื่องปลายทางมากกว่าขนาดข้อมูลที่จะสำรอง
- ติดตั้ง rsync ทั้งสองเครื่อง:
sudo apt install -y rsyncหรือsudo dnf install -y rsync
ตัวอย่างนี้สำรองโฟลเดอร์ /var/www หากต้องการสำรองฐานข้อมูลด้วย ให้ Dump ฐานข้อมูลเป็นไฟล์ก่อนตามคู่มือ สำรองและกู้คืนฐานข้อมูล MySQL/MariaDB ด้วย mysqldump แล้วให้ rsync ส่งโฟลเดอร์ไฟล์ Dump ไปด้วย
ขั้นตอนที่ 1: เตรียมผู้ใช้และโฟลเดอร์บนเครื่องปลายทาง
บนเครื่องปลายทาง สร้างผู้ใช้ backup และโฟลเดอร์รับไฟล์
sudo useradd -m -s /bin/bash backup
sudo mkdir -p /srv/backup/web01
sudo chown backup:backup /srv/backup/web01บน Ubuntu อาจมีผู้ใช้ระบบชื่อ backup อยู่แล้ว หาก useradd แจ้งว่ามีผู้ใช้นี้ ให้ใช้ชื่ออื่น เช่น bkuser และเปลี่ยนชื่อในทุกคำสั่งให้ตรงกัน
ขั้นตอนที่ 2: สร้าง SSH Key สำหรับงานสำรองข้อมูล
Cronjob รันโดยไม่มีคนพิมพ์รหัสผ่าน จึงต้องใช้ SSH Key ที่ไม่มี Passphrase แยกไว้สำหรับงานนี้โดยเฉพาะ บนเครื่องต้นทาง ให้ทำในฐานะ root เพราะต้องอ่านไฟล์ได้ทุกไฟล์
sudo ssh-keygen -t ed25519 -f /root/.ssh/backup_ed25519 -N "" -C "backup web01"
sudo cat /root/.ssh/backup_ed25519.pubคัดลอกข้อความ Public Key ที่ได้ แล้วนำไปใส่ในไฟล์ /home/backup/.ssh/authorized_keys บนเครื่องปลายทาง
sudo -u backup mkdir -p /home/backup/.ssh
sudo -u backup nano /home/backup/.ssh/authorized_keys
sudo chmod 700 /home/backup/.ssh
sudo chmod 600 /home/backup/.ssh/authorized_keysจากนั้นทดสอบการเชื่อมต่อจากเครื่องต้นทาง ครั้งแรกต้องทำด้วยมือ เพื่อตอบ yes ยืนยัน Host Key ของเครื่องปลายทาง ไม่เช่นนั้น Cronjob จะล้มเหลว
sudo ssh -i /root/.ssh/backup_ed25519 [email protected] 'echo connected'ถ้าได้คำว่า connected โดยไม่ถามรหัสผ่าน แสดงว่าพร้อมแล้ว หากเครื่องปลายทางเปลี่ยน SSH Port ไว้ ให้เติม -p 2222 (ใช้พอร์ตจริง) ต่อจาก ssh ดูรายละเอียดเรื่อง SSH Key เพิ่มเติมได้ที่ ตั้งค่า SSH Key และปิดการเข้าสู่ระบบด้วยรหัสผ่านบน Linux
ขั้นตอนที่ 3: ทดลองรัน rsync แบบจำลองก่อน
sudo rsync -aHz --delete --dry-run --itemize-changes \
-e "ssh -i /root/.ssh/backup_ed25519" \
/var/www/ [email protected]:/srv/backup/web01/www/ความหมายของตัวเลือก
-aคัดลอกแบบเก็บสิทธิ์ เจ้าของ เวลา และ Symlink ครบ-Hรักษา Hard Link-zบีบอัดข้อมูลระหว่างส่ง--deleteลบไฟล์ฝั่งปลายทางที่ไม่มีแล้วในต้นทาง ให้สองฝั่งตรงกัน--dry-runแสดงว่าจะทำอะไรโดยยังไม่ทำจริง
หมายเหตุ: เครื่องหมาย
/ท้าย Path ต้นทางมีผล/var/www/หมายถึงคัดลอก เนื้อหาใน โฟลเดอร์ ส่วน/var/wwwจะสร้างโฟลเดอร์wwwซ้อนเข้าไปอีกชั้น และเมื่อใช้--deleteถ้าระบุ Path ปลายทางผิด ไฟล์ในโฟลเดอร์นั้นจะถูกลบ จึงต้องตรวจผลจาก--dry-runทุกครั้งก่อนรันจริง
เมื่อตรวจรายการแล้วถูกต้อง ให้รันซ้ำโดยตัด --dry-run ออก รอบแรกจะใช้เวลานานตามขนาดข้อมูล รอบต่อไปจะเร็วขึ้นมาก
ขั้นตอนที่ 4: เขียนสคริปต์สำรองข้อมูล
sudo nano /usr/local/bin/backup-web.sh#!/bin/bash
set -euo pipefail
DEST="[email protected]:/srv/backup/web01"
SSH="ssh -i /root/.ssh/backup_ed25519 -o BatchMode=yes"
echo "=== $(date '+%F %T') start"
rsync -aHz --delete --exclude 'cache/' -e "$SSH" /var/www/ "$DEST/www/"
rsync -aHz --delete -e "$SSH" /etc/nginx/ "$DEST/nginx/"
echo "=== $(date '+%F %T') done"sudo chmod 700 /usr/local/bin/backup-web.sh
sudo /usr/local/bin/backup-web.shset -euo pipefail ทำให้สคริปต์หยุดทันทีเมื่อคำสั่งใดล้มเหลว และ BatchMode=yes ทำให้ SSH ไม่ค้างรอรหัสผ่านหากใช้ Key ไม่ได้ ปรับ --exclude และรายการโฟลเดอร์ให้ตรงกับเซิร์ฟเวอร์ของคุณ