Feb 2026 • DevOps Guide

เทคนิค Sync ไฟล์จำนวนมาก

ระหว่าง Server สองตัว ผ่าน Internet

คู่มือใช้งาน rsync, Unison, rclone, lsyncd และ Script อัตโนมัติ
พร้อมวิธีแก้ปัญหาที่พบบ่อย เหมาะสำหรับ DevOps และ System Admin

Linux
Server
Network
Script

1. บทนำ

การ sync ไฟล์จำนวนมากระหว่าง Server สองตัวผ่าน Internet เป็นงานที่พบบ่อยในงาน DevOps และ System Administration ไม่ว่าจะเป็นการ backup ข้อมูล, การ migrate server, หรือการทำ High Availability setup บทความนี้จะแนะนำเครื่องมือ Open-Source ยอดนิยม พร้อมวิธีใช้งานและ Script ตัวอย่างที่สามารถนำไปใช้ได้ทันที

🎯 Use Cases ที่พบบ่อย

  • Backup ข้อมูล: sync ไฟล์จาก Production Server ไป Backup Server
  • Migration: ย้ายข้อมูลจาก Server เก่าไป Server ใหม่
  • Load Balancing: sync ไฟล์ static content ระหว่างหลายๆ web server
  • Disaster Recovery: สำรองข้อมูลไปยัง Data Center สำรอง
  • Development: sync ไฟล์ระหว่าง Development และ Production environment

🏗️ Architecture Overview

Source Server 192.168.1.10 /var/www/html/ 500GB Data SYNC rsync/unison/rclone Internet SSH/HTTPS Destination Server 192.168.2.20 /backup/www/ Mirror Copy Primary Secondary

2. เปรียบเทียบเครื่องมือ

เครื่องมือ ทิศทาง ความเร็ว Real-time Use Case หลัก ความยาก
rsync One-way เร็วมาก ไม่ Backup, Migration ง่าย
Unison Bidirectional ปานกลาง ไม่ Sync 2 ทาง ปานกลาง
rclone Both ปานกลาง ไม่ Cloud Storage ปานกลาง
lsyncd One-way เร็วมาก ใช่ Real-time Sync ยาก

💡 คำแนะนำ

สำหรับการ sync ไฟล์จำนวนมากครั้งแรก แนะนำให้ใช้ rsync เพราะเร็วที่สุดและใช้งานง่าย หากต้องการ sync 2 ทางให้ใช้ Unison และหากต้องการ real-time ให้ใช้ lsyncd

3. rsync (แนะนำ)

rsync คืออะไร?

rsync (remote sync) เป็นเครื่องมือ sync ไฟล์ที่มีประสิทธิภาพสูงที่สุด ใช้ algorithm ที่เรียกว่า "delta-transfer" ที่ส่งเฉพาะส่วนที่เปลี่ยนแปลงของไฟล์ ทำให้ประหยัด bandwidth และเวลาอย่างมาก

ข้อดี

  • • เร็วที่สุดสำหรับไฟล์ขนาดใหญ่
  • • ส่งเฉพาะส่วนที่เปลี่ยนแปลง
  • • รองรับ SSH encryption
  • • Resume ได้หากขาดหาย
  • • มีในทุก Linux distro

ข้อจำกัด

  • • Sync ได้ทิศทางเดียวเท่านั้น
  • • ไม่รองรับ real-time
  • • ต้องมี rsync ทั้งสองฝั่ง
  • • การ config ที่ซับซ้อนสำหรับ advanced use

การติดตั้ง

Ubuntu/Debian
# ติดตั้ง rsync
sudo apt update
sudo apt install rsync -y

# ตรวจสอบ version
rsync --version

# เปิดใช้งาน rsync daemon (ถ้าต้องการ)
sudo systemctl enable rsync
sudo systemctl start rsync
CentOS/RHEL
# ติดตั้ง rsync
sudo yum install rsync -y

# หรือสำหรับ RHEL 8+
sudo dnf install rsync -y

# ตรวจสอบ version
rsync --version
Fedora
# ติดตั้ง rsync
sudo dnf install rsync -y

# ตรวจสอบ version
rsync --version

การใช้งานพื้นฐาน

Basic rsync Command
# Syntax พื้นฐาน
rsync [options] source destination

# Sync โฟลเดอร์ไปยัง remote server
rsync -avz /local/path/ user@remote-server:/remote/path/

# Sync จาก remote server มา local
rsync -avz user@remote-server:/remote/path/ /local/path/

# Sync ระหว่างสอง remote servers (ผ่าน local)
rsync -avz user@server1:/path/ user@server2:/path/

📋 Options ที่สำคัญ

-a -- Archive mode (รักษา permissions, timestamps)
-v -- Verbose (แสดงรายละเอียด)
-z -- Compress (บีบอัดข้อมูล)
-h -- Human-readable format
--progress -- แสดง progress bar
--delete -- ลบไฟล์ที่ไม่มีใน source
--exclude -- ยกเว้นไฟล์/โฟลเดอร์
--bwlimit -- จำกัด bandwidth (KB/s)

ตัวอย่างขั้นสูง

1. Sync ไฟล์จำนวนมากพร้อม Progress
# Sync ไฟล์ทั้งหมดพร้อมแสดง progress
rsync -avzh --progress /var/www/html/ user@backup-server:/backup/www/

# Output ตัวอย่าง:
# sending incremental file list
# file1.jpg
#     1.23M 100%    1.23MB/s    0:00:01 (xfr#1, to-chk=99/101)
# file2.pdf
#     5.67M 100%    2.34MB/s    0:00:02 (xfr#2, to-chk=98/101)
2. Sync พร้อมจำกัด Bandwidth
# จำกัดความเร็วที่ 10MB/s (10240 KB/s)
rsync -avz --bwlimit=10240 /data/ user@remote:/backup/data/

# จำกัดที่ 5MB/s
rsync -avz --bwlimit=5120 /data/ user@remote:/backup/data/

# เหมาะสำหรับ sync ในเวลาทำการเพื่อไม่ให้กระทบ network
3. Sync พร้อม Exclude ไฟล์
# Exclude โฟลเดอร์ cache และ log
rsync -avz --exclude 'cache/' --exclude 'logs/*.log' \
  /var/www/ user@remote:/backup/www/

# Exclude หลายรูปแบบ
rsync -avz \
  --exclude '*.tmp' \
  --exclude '*.bak' \
  --exclude '.git/' \
  --exclude 'node_modules/' \
  /project/ user@remote:/backup/project/

# ใช้ไฟล์ exclude list
rsync -avz --exclude-from='/path/to/exclude-list.txt' \
  /data/ user@remote:/backup/data/
4. Resume การ Sync ที่ขาดหาย
# ใช้ --partial เพื่อเก็บไฟล์ที่ sync ไม่เสร็จ
rsync -avz --partial --progress /large-files/ user@remote:/backup/

# หากขาดหาย สั่งใหม่จะต่อจากที่ค้างไว้
# rsync จะตรวจสอบและส่งต่อจากจุดที่หยุด

# แนะนำให้ใช้ --partial-dir เพื่อเก็บไฟล์ partial แยก
rsync -avz --partial-dir=.rsync-partial /data/ user@remote:/backup/
5. Sync ผ่าน SSH Port ที่ไม่ใช่ 22
# Sync ผ่าน SSH port 2222
rsync -avz -e 'ssh -p 2222' /data/ user@remote:/backup/

# Sync ผ่าน SSH พร้อม key file
rsync -avz -e 'ssh -i /path/to/key.pem -p 2222' \
  /data/ user@remote:/backup/

# ใช้ SSH config จากไฟล์
rsync -avz -e 'ssh -F /path/to/ssh_config' /data/ user@remote:/backup/

ตั้งค่า SSH Key สำหรับ Passwordless Sync

การใช้ SSH Key ทำให้สามารถ sync อัตโนมัติผ่าน cron job ได้โดยไม่ต้องใส่ password

SSH Key Setup
# 1. สร้าง SSH key บน Source Server
ssh-keygen -t rsa -b 4096 -f ~/.ssh/rsync_key -N ""

# 2. Copy public key ไปยัง Destination Server
ssh-copy-id -i ~/.ssh/rsync_key.pub user@destination-server

# หรือ manual copy
cat ~/.ssh/rsync_key.pub | ssh user@destination-server \
  "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 3. ทดสอบ connection
ssh -i ~/.ssh/rsync_key user@destination-server

# 4. ใช้ rsync กับ key
rsync -avz -e 'ssh -i ~/.ssh/rsync_key' /data/ user@destination:/backup/

4. Unison (Bidirectional Sync)

Unison คืออะไร?

Unison เป็นเครื่องมือ sync ไฟล์ 2 ทาง (bidirectional) ที่สามารถ sync การเปลี่ยนแปลงจากทั้งสองฝั่ง เหมาะสำหรับกรณีที่ต้องการให้ไฟล์ทั้งสอง server เหมือนกันเสมอ โดย Unison จะจัดการ conflict ให้อัตโนมัติ

Server A /data/shared/ Server B /data/shared/ Changes A→B Changes B→A

การติดตั้ง Unison

ติดตั้ง Unison (ต้องติดตั้งทั้งสอง server)
# Ubuntu/Debian
sudo apt update
sudo apt install unison -y

# CentOS/RHEL
sudo yum install unison -y

# ตรวจสอบ version (ต้องเท่ากันทั้งสองฝั่ง)
unison -version

สำคัญ: Unison version ทั้งสอง server ต้องเหมือนกัน ไม่เช่นนั้นจะ sync ไม่ได้

การตั้งค่า Unison Profile

~/.unison/default.prf
# สร้าง profile file
mkdir -p ~/.unison
nano ~/.unison/default.prf
default.prf Content
# Unison Configuration File

# Roots - ที่อยู่ของโฟลเดอร์ที่จะ sync
root = /data/shared/
root = ssh://user@server-b//data/shared/

# SSH settings
sshargs = -i ~/.ssh/unison_key -p 22

# Sync options
auto = true              # อัตโนมัติ ไม่ถาม
batch = true             # Batch mode
prefer = newer           # เลือกไฟล์ที่ใหม่กว่ากรณี conflict
confirmbigdel = false    # ไม่ถามก่อนลบไฟล์จำนวนมาก

# Logging
log = true
logfile = ~/.unison/unison.log

# Ignore patterns
ignore = Name *.tmp
ignore = Name *.log
ignore = Name .git
ignore = Name node_modules
ignore = Path */cache/*

# Fastcheck (ใช้ file modification time)
fastcheck = true

# รักษา permissions และ owner
perms = true
owner = true
group = true

การใช้งาน Unison

Unison Commands
# Sync ด้วย default profile
unison default

# Sync แบบ interactive (แสดง changes ก่อน)
unison -ui text default

# Sync แบบ silent (สำหรับ cron)
unison -batch default

# Sync ด้วย profile อื่น
unison myprofile

# Force ให้ฝั่ง local เป็นหลัก
unison -force /data/shared/ default

# Force ให้ฝั่ง remote เป็นหลัก
unison -force ssh://user@server-b//data/shared/ default

# ทดสอบ dry-run (ไม่ sync จริง)
unison -dry-run default

5. rclone (Cloud Storage Sync)

rclone คืออะไร?

rclone เป็นเครื่องมือ sync ไฟล์กับ Cloud Storage หลากหลาย provider รองรับมากกว่า 40 providers รวมถึง Google Drive, Dropbox, S3, Azure Blob, Backblaze B2 และอื่นๆ เหมาะสำหรับ backup ข้อมูลขึ้น Cloud

Google Drive

Dropbox

AWS S3

Azure Blob

การติดตั้ง rclone

Install rclone
# ติดตั้งด้วย script
curl https://rclone.org/install.sh | sudo bash

# หรือด้วย package manager
# Ubuntu/Debian
sudo apt update
sudo apt install rclone -y

# CentOS/RHEL
sudo yum install rclone -y

# ตรวจสอบ version
rclone version

การตั้งค่า Remote

Interactive Setup
# เริ่มต้น configuration
rclone config

# จะมี interactive wizard ช่วยตั้งค่า
# เลือก storage type และใส่ credentials
rclone.conf Example (S3)
# ~/.config/rclone/rclone.conf

[my-s3]
type = s3
provider = AWS
env_auth = false
access_key_id = YOUR_ACCESS_KEY
secret_access_key = YOUR_SECRET_KEY
region = ap-southeast-1
acl = private

[my-gdrive]
type = drive
client_id = YOUR_CLIENT_ID
client_secret = YOUR_CLIENT_SECRET
scope = drive
token = {"access_token":"...","token_type":"Bearer","refresh_token":"..."}

การใช้งาน rclone

rclone sync Commands
# Sync local ไป S3
rclone sync /data/backup my-s3:my-bucket/backup --progress

# Sync S3 มา local
rclone sync my-s3:my-bucket/backup /data/backup --progress

# Sync ระหว่าง S3 buckets
rclone sync my-s3:bucket1 my-s3:bucket2 --progress

# Sync ไป Google Drive
rclone sync /data/ my-gdrive:backup/ --progress

# Copy (ไม่ลบไฟล์ที่ปลายทาง)
rclone copy /data/ my-s3:bucket/data/ --progress

# แสดงรายการไฟล์
rclone ls my-s3:my-bucket/backup

# ตรวจสอบความแตกต่าง
rclone check /data/ my-s3:bucket/data/
rclone Options ที่มีประโยชน์
# จำกัด bandwidth
rclone sync /data/ remote:bucket/ --bwlimit 10M

# Exclude patterns
rclone sync /data/ remote:bucket/ \
  --exclude "*.log" \
  --exclude "cache/**" \
  --exclude ".git/**"

# Dry run (ทดสอบ)
rclone sync /data/ remote:bucket/ --dry-run

# แบ่งไฟล์ใหญ่
rclone sync /data/ remote:bucket/ \
  --s3-chunk-size 100M \
  --s3-upload-concurrency 4

# Encrypt ข้อมูล
rclone sync /data/ crypt:backup/ --progress

6. lsyncd (Real-time Sync)

lsyncd คืออะไร?

lsyncd (Live Syncing Daemon) เป็นเครื่องมือ sync ไฟล์แบบ real-time ที่ใช้ inotify เพื่อ monitor file system changes และ sync ทันทีที่มีการเปลี่ยนแปลง เหมาะสำหรับ High Availability setup

lsyncd เหมาะสำหรับ sync ไฟล์ static content, configuration files, หรือ web assets ที่ต้องการให้ sync ทันที

inotify monitor lsyncd process rsync sync Remote event trigger sync

การติดตั้ง lsyncd

Install lsyncd
# Ubuntu/Debian
sudo apt update
sudo apt install lsyncd -y

# CentOS/RHEL
sudo yum install lsyncd -y

# สร้างโฟลเดอร์ config
sudo mkdir -p /etc/lsyncd

# ตรวจสอบ version
lsyncd --version

การตั้งค่า lsyncd

/etc/lsyncd/lsyncd.conf.lua
-- lsyncd configuration file

settings {
    logfile = "/var/log/lsyncd/lsyncd.log",
    statusFile = "/var/log/lsyncd/lsyncd.status",
    statusInterval = 20,
    nodaemon = false,
    maxProcesses = 4,
}

-- Sync ไปยัง remote server เดียว
sync {
    default.rsync,
    source = "/var/www/html/",
    target = "user@backup-server:/backup/www/",
    delete = true,
    delay = 5,
    rsync = {
        binary = "/usr/bin/rsync",
        archive = true,
        compress = true,
        verbose = true,
        _extra = {"--bwlimit=10240"}
    },
    exclude = {
        "*.log",
        "*.tmp",
        "cache/",
        ".git/"
    }
}

-- Sync ไปยังหลาย remote servers
sync {
    default.rsync,
    source = "/var/www/html/",
    target = "user@server1:/var/www/html/",
    -- ... options
}

sync {
    default.rsync,
    source = "/var/www/html/",
    target = "user@server2:/var/www/html/",
    -- ... options
}

การใช้งาน lsyncd

Start lsyncd
# สร้างโฟลเดอร์ log
sudo mkdir -p /var/log/lsyncd

# ทดสอบ config
sudo lsyncd -nodaemon -log Exec /etc/lsyncd/lsyncd.conf.lua

# Start service
sudo systemctl enable lsyncd
sudo systemctl start lsyncd

# ตรวจสอบ status
sudo systemctl status lsyncd

# ดู log
sudo tail -f /var/log/lsyncd/lsyncd.log

# ดู status file
cat /var/log/lsyncd/lsyncd.status

7. Script อัตโนมัติ

Script 1: Backup Sync Script พร้อม Logging

/usr/local/bin/backup-sync.sh
#!/bin/bash
#
# Backup Sync Script
# Usage: ./backup-sync.sh [source] [destination]
#

set -e

# Configuration
SOURCE_DIR="${1:-/var/www/html/}"
DEST_USER="backup"
DEST_SERVER="backup.example.com"
DEST_DIR="${2:-/backup/www/}"
LOG_FILE="/var/log/backup-sync.log"
LOCK_FILE="/var/run/backup-sync.lock"
EMAIL="admin@example.com"

# Functions
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

send_alert() {
    local subject="$1"
    local message="$2"
    echo "$message" | mail -s "$subject" "$EMAIL"
}

# Check if already running
if [ -f "$LOCK_FILE" ]; then
    PID=$(cat "$LOCK_FILE")
    if ps -p "$PID" > /dev/null 2>&1; then
        log "ERROR: Script already running (PID: $PID)"
        exit 1
    else
        rm -f "$LOCK_FILE"
    fi
fi

# Create lock file
echo $$ > "$LOCK_FILE"

# Start sync
log "Starting backup sync from $SOURCE_DIR to $DEST_SERVER:$DEST_DIR"

START_TIME=$(date +%s)

rsync -avz \
    --delete \
    --progress \
    --stats \
    --log-file="$LOG_FILE" \
    --exclude='*.log' \
    --exclude='cache/' \
    --exclude='.git/' \
    --bwlimit=10240 \
    -e 'ssh -i /root/.ssh/backup_key -p 22 -o StrictHostKeyChecking=no' \
    "$SOURCE_DIR" \
    "${DEST_USER}@${DEST_SERVER}:${DEST_DIR}"

RSYNC_EXIT_CODE=$?

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

if [ $RSYNC_EXIT_CODE -eq 0 ]; then
    log "Backup sync completed successfully in ${DURATION} seconds"
    send_alert "Backup Sync Success" "Backup completed in ${DURATION} seconds"
else
    log "ERROR: Backup sync failed with exit code $RSYNC_EXIT_CODE"
    send_alert "Backup Sync FAILED" "Backup failed with exit code $RSYNC_EXIT_CODE"
fi

# Remove lock file
rm -f "$LOCK_FILE"

exit $RSYNC_EXIT_CODE

Script 2: Bidirectional Sync Script

/usr/local/bin/bidirectional-sync.sh
#!/bin/bash
#
# Bidirectional Sync Script using Unison
#

set -e

# Configuration
LOCAL_DIR="/data/shared"
REMOTE_USER="sync"
REMOTE_HOST="server-b.example.com"
REMOTE_DIR="/data/shared"
SSH_KEY="/root/.ssh/unison_key"
LOG_FILE="/var/log/bidirectional-sync.log"
PROFILE="shared-sync"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# Create temporary profile
TEMP_PROFILE="/tmp/${PROFILE}.prf"
cat > "$TEMP_PROFILE" <&1 | while read line; do
    log "$line"
done

UNISON_EXIT=$?

if [ $UNISON_EXIT -eq 0 ]; then
    log "Bidirectional sync completed successfully"
else
    log "ERROR: Bidirectional sync failed with exit code $UNISON_EXIT"
fi

# Cleanup
rm -f "$TEMP_PROFILE"

exit $UNISON_EXIT

Script 3: Multi-Server Sync Script

/usr/local/bin/multi-server-sync.sh
#!/bin/bash
#
# Multi-Server Sync Script
# Sync ไปยังหลาย servers พร้อมกัน
#

set -e

SOURCE_DIR="/var/www/html/"
SSH_KEY="/root/.ssh/sync_key"
BWLIMIT="10240"
LOG_FILE="/var/log/multi-sync.log"

# Server list (user@host:destination)
SERVERS=(
    "deploy@web1.example.com:/var/www/html/"
    "deploy@web2.example.com:/var/www/html/"
    "deploy@web3.example.com:/var/www/html/"
    "backup@backup.example.com:/backup/www/"
)

# Parallel sync function
sync_to_server() {
    local server="$1"
    local start_time=$(date +%s)
    
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting sync to $server" >> "$LOG_FILE"
    
    if rsync -avz \
        --delete \
        --bwlimit="$BWLIMIT" \
        --exclude='*.log' \
        --exclude='cache/' \
        -e "ssh -i $SSH_KEY -o StrictHostKeyChecking=no -o ConnectTimeout=30" \
        "$SOURCE_DIR" \
        "$server" >> "$LOG_FILE" 2>&1; then
        
        local end_time=$(date +%s)
        local duration=$((end_time - start_time))
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $server (${duration}s)" >> "$LOG_FILE"
        return 0
    else
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] FAILED: $server" >> "$LOG_FILE"
        return 1
    fi
}

# Main
echo "========================================" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting multi-server sync" >> "$LOG_FILE"

PIDS=()
SUCCESS=0
FAILED=0

# Start parallel syncs
for server in "${SERVERS[@]}"; do
    sync_to_server "$server" &
    PIDS+=($!)
done

# Wait for all syncs to complete
for pid in "${PIDS[@]}"; do
    if wait $pid; then
        ((SUCCESS++))
    else
        ((FAILED++))
    fi
done

# Summary
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Multi-server sync completed" >> "$LOG_FILE"
echo "  Success: $SUCCESS" >> "$LOG_FILE"
echo "  Failed: $FAILED" >> "$LOG_FILE"

if [ $FAILED -gt 0 ]; then
    exit 1
fi

exit 0

Script 4: Incremental Backup with Rotation

/usr/local/bin/incremental-backup.sh
#!/bin/bash
#
# Incremental Backup with Rotation
# ใช้ hardlinks เพื่อประหยัดพื้นที่
#

set -e

# Configuration
SOURCE_DIR="/var/www/html/"
BACKUP_BASE="/backup/www"
REMOTE_USER="backup"
REMOTE_HOST="backup.example.com"
KEEP_DAILY=7
KEEP_WEEKLY=4
KEEP_MONTHLY=12

# Date variables
DATE=$(date +%Y-%m-%d)
DAY_OF_WEEK=$(date +%u)
DAY_OF_MONTH=$(date +%d)

# Backup directories
DAILY_DIR="${BACKUP_BASE}/daily"
WEEKLY_DIR="${BACKUP_BASE}/weekly"
MONTHLY_DIR="${BACKUP_BASE}/monthly"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# Create directories
mkdir -p "$DAILY_DIR" "$WEEKLY_DIR" "$MONTHLY_DIR"

# Find latest backup for hardlink reference
LATEST_BACKUP=$(ls -1d "${DAILY_DIR}"/*/ 2>/dev/null | tail -1)

# Create new backup using hardlinks
NEW_BACKUP="${DAILY_DIR}/${DATE}"
log "Creating incremental backup: $NEW_BACKUP"

if [ -n "$LATEST_BACKUP" ]; then
    # Use rsync with link-dest for incremental backup
    rsync -avz \
        --delete \
        --link-dest="$LATEST_BACKUP" \
        --exclude='*.log' \
        --exclude='cache/' \
        -e 'ssh -i /root/.ssh/backup_key' \
        "${REMOTE_USER}@${REMOTE_HOST}:${SOURCE_DIR}" \
        "$NEW_BACKUP/"
else
    # First backup - full copy
    rsync -avz \
        --delete \
        --exclude='*.log' \
        --exclude='cache/' \
        -e 'ssh -i /root/.ssh/backup_key' \
        "${REMOTE_USER}@${REMOTE_HOST}:${SOURCE_DIR}" \
        "$NEW_BACKUP/"
fi

log "Backup created successfully"

# Weekly backup (Sunday)
if [ "$DAY_OF_WEEK" -eq 7 ]; then
    log "Creating weekly backup"
    cp -al "$NEW_BACKUP" "${WEEKLY_DIR}/${DATE}"
fi

# Monthly backup (1st of month)
if [ "$DAY_OF_MONTH" -eq 01 ]; then
    log "Creating monthly backup"
    cp -al "$NEW_BACKUP" "${MONTHLY_DIR}/${DATE}"
fi

# Rotation - delete old backups
log "Rotating old backups..."

# Daily rotation
find "$DAILY_DIR" -maxdepth 1 -type d -mtime +$KEEP_DAILY -exec rm -rf {} \; 2>/dev/null || true

# Weekly rotation
find "$WEEKLY_DIR" -maxdepth 1 -type d -mtime +$((KEEP_WEEKLY * 7)) -exec rm -rf {} \; 2>/dev/null || true

# Monthly rotation
find "$MONTHLY_DIR" -maxdepth 1 -type d -mtime +$((KEEP_MONTHLY * 30)) -exec rm -rf {} \; 2>/dev/null || true

log "Backup rotation completed"

# Calculate backup sizes
DAILY_SIZE=$(du -sh "$DAILY_DIR" | cut -f1)
log "Daily backup size: $DAILY_SIZE"

# Send summary
echo "Backup completed successfully on $(date)" | mail -s "Backup Summary - $(hostname)" admin@example.com

exit 0

Cron Job Setup

/etc/cron.d/sync-jobs
# File sync cron jobs

# Sync ทุก 6 ชั่วโมง
0 */6 * * * root /usr/local/bin/backup-sync.sh >> /var/log/sync-cron.log 2>&1

# Bidirectional sync ทุก 15 นาที
*/15 * * * * root /usr/local/bin/bidirectional-sync.sh >> /var/log/unison-cron.log 2>&1

# Multi-server sync วันละครั้ง เวลา 2:00 AM
0 2 * * * root /usr/local/bin/multi-server-sync.sh >> /var/log/multi-sync-cron.log 2>&1

# Incremental backup วันละครั้ง เวลา 3:00 AM
0 3 * * * root /usr/local/bin/incremental-backup.sh >> /var/log/backup-cron.log 2>&1

# Cloud sync ทุกวันอาทิตย์ เวลา 4:00 AM
0 4 * * 0 root rclone sync /backup/ my-s3:bucket/backup/ --log-file=/var/log/rclone-cron.log

8. แก้ไขปัญหาที่พบบ่อย

ปัญหา: rsync Connection Refused

rsync: failed to connect to 192.168.1.100 (192.168.1.100): Connection refused (111)
rsync error: error in socket IO (code 10) at clientserver.c(139) [sender=3.2.7]

วิธีแก้:

# 1. ตรวจสอบว่า SSH service ทำงาน
sudo systemctl status sshd

# 2. ตรวจสอบ firewall
sudo ufw status
sudo ufw allow 22/tcp

# 3. ตรวจสอบว่า rsync ติดตั้งทั้งสองฝั่ง
which rsync
ssh user@remote "which rsync"

# 4. ทดสอบ SSH connection
ssh -v user@remote-server

ปัญหา: Permission Denied

rsync: send_files failed to open "/var/www/html/config.php": Permission denied (13)
rsync error: some files/attrs were not transferred (see previous errors)

วิธีแก้:

# 1. ตรวจสอบ file permissions
ls -la /var/www/html/

# 2. แก้ไข permissions
sudo chmod -R 755 /var/www/html/
sudo chown -R www-data:www-data /var/www/html/

# 3. ใช้ sudo กับ rsync (ถ้าจำเป็น)
rsync -avz --rsync-path="sudo rsync" /source/ user@remote:/dest/

# 4. เพิ่ม user ใน sudoers (ที่ remote server)
echo "backup ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/backup

ปัญหา: Out of Memory (ไฟล์ขนาดใหญ่มาก)

rsync: writefd_unbuffered failed to write 4 bytes [sender]: Broken pipe (32)
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [sender=3.2.7]

วิธีแก้:

# 1. ใช้ --partial เพื่อ resume
rsync -avz --partial --progress /large-file user@remote:/dest/

# 2. แบ่งไฟล์ใหญ่เป็นส่วนๆ
split -b 1G large-file.tar large-file-part-
rsync -avz large-file-part-* user@remote:/dest/
# ที่ remote: cat large-file-part-* > large-file.tar

# 3. ลด buffer size
rsync -avz --block-size=8192 /data/ user@remote:/dest/

# 4. เพิ่ม swap (ถ้าจำเป็น)
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

ปัญหา: SSH Key Authentication Failed

Permission denied (publickey,password).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]

วิธีแก้:

# 1. ตรวจสอบ SSH key permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

# 2. ทดสอบ SSH key
ssh -i ~/.ssh/sync_key -v user@remote

# 3. ตรวจสอบ authorized_keys ที่ remote
cat ~/.ssh/authorized_keys

# 4. เพิ่ม key ใหม่
ssh-copy-id -i ~/.ssh/sync_key.pub user@remote

# 5. ตรวจสอบ SSH config
grep -E "PubkeyAuthentication|AuthorizedKeysFile" /etc/ssh/sshd_config

# 6. ใช้ SSH agent
eval $(ssh-agent -s)
ssh-add ~/.ssh/sync_key

ปัญหา: Sync ช้าเกินไป

วิธีแก้:

# 1. ใช้ compression น้อยลง (CPU vs Bandwidth)
rsync -avz --compress-level=1 /data/ user@remote:/dest/

# 2. ใช้ parallel transfers (สำหรับไฟล์เล็กจำนวนมาก)
# ติดตั้ง parallel
sudo apt install parallel

# ใช้ parallel rsync
find /data/ -type f | parallel -j 4 rsync -avz {} user@remote:/dest/

# 3. ใช้ --whole-file สำหรับ network เร็ว
rsync -avz --whole-file /data/ user@remote:/dest/

# 4. เพิ่ม SSH encryption speed
rsync -avz -e 'ssh -c aes128-ctr' /data/ user@remote:/dest/

# 5. ใช้ rsync daemon แทน SSH (เร็วกว่า)
# ที่ remote: /etc/rsyncd.conf
[backup]
    path = /backup
    read only = no
    auth users = backup
    secrets file = /etc/rsyncd.secrets

# Sync ผ่าน rsync daemon
rsync -avz /data/ backup@remote::backup/

ปัญหา: Unison Version Mismatch

Fatal error: Exception Unison.Failure("Unison version mismatch: server has 2.51.2, client has 2.48.4")

วิธีแก้:

# 1. ตรวจสอบ version ทั้งสองฝั่ง
unison -version
ssh user@remote "unison -version"

# 2. ติดตั้ง version เดียวกัน
# ดาวน์โหลดจาก https://github.com/bcpierce00/unison/releases

# Ubuntu 20.04+
sudo apt install unison -y

# ถ้าไม่มีใน repo ให้ compile เอง
sudo apt install build-essential ocaml
wget https://github.com/bcpierce00/unison/archive/refs/tags/v2.52.1.tar.gz
tar xzf v2.52.1.tar.gz
cd unison-2.52.1
make UISTYLE=text
sudo cp src/unison /usr/local/bin/
sudo cp src/unison-fsmonitor /usr/local/bin/

# 3. ใช้ OCaml version เดียวกัน
ocaml -version

Best Practices สรุป

✅ ควรทำ

  • • ใช้ SSH key แทน password
  • • จำกัด bandwidth ในเวลาทำการ
  • • ใช้ --dry-run ทดสอบก่อน
  • • เก็บ log และ monitor sync status
  • • ทำ incremental backup สำหรับไฟล์ใหญ่
  • • ใช้ lock file ป้องกัน sync ซ้อน

❌ ควรหลีกเลี่ยง

  • • อย่าใช้ --delete โดยไม่ทดสอบก่อน
  • • อย่า sync ขณะ disk เต็ม
  • • อย่าลืม exclude ไฟล์ชั่วคราว
  • • อย่า sync ไฟล์ที่เปิดอยู่ (database files)
  • • อย่าลืม backup config files
  • • อย่าใช้ version ไม่ตรงกัน (Unison)