MITOM

← Danh sách bài viết

Nội dung được biên soạn lại từ Anh Nguyen - kèm nguồn bài viết (nếu có)

Tự động backup nhiều WordPress store từ một hosting / VPS lên Amazon S3Google Drive, kèm:


1. Folder structure

Giả sử user là USER:

/home/USER/
  ├─ domains/
  │   ├─ domain1.com/public_html
  │   ├─ domain2.com/public_html
  │   └─ ...
  ├─ backups/                  # backup cho Bash script
  │   └─ 2025-11-21/
  │        ├─ store1/
  │        │    ├─ files_store1_2025-11-21.tar.gz
  │        │    └─ db_store1_2025-11-21.sql.gz
  │        ├─ store2/
  │        │    ├─ files_store2_2025-11-21.tar.gz
  │        │    └─ db_store2_2025-11-21.sql.gz
  │        └─ ...
  ├─ backups-php/              # backup cho PHP script
  │   └─ 2025-11-21/
  │        ├─ store1/
  │        │    ├─ db_store1_com_2025-11-23.sql.gz
  │        │    └─ files_store1_com_2025-11-23.zip
  ├─ logs/
  │   ├─ backup_*.log
  │   └─ backup_php_*.log
  ├─ scripts/
  │   └─ backup_all_stores.sh
  └─ scripts-php-backup/
      ├─ backup_all_stores.php
      └─ vendor/               # PHP libraries (Composer)

2. Yêu cầu chung

2.1. So sánh AWS S3 vs Google Drive lưu backup

2.1.1. Amazon S3

Ưu điểm

Nhược điểm

2.1.2. Google Drive

Ưu điểm

Nhược điểm

Kết luận:

2.2. Run backup Bash script hay PHP script?

2.2.1. Bash script

Ưu điểm

Nhược điểm

2.2.2. PHP script chạy CLI

Ưu điểm

Nhược điểm

Gợi ý chọn:

3. Kiểm tra & chuẩn bị môi trường (PHP và Bash)

3.1. Bật SSH & kiểm tra cơ bản

Sau khi SSH vào:

whoami
pwd
ls -la
uname -a

Nếu các lệnh này OK → SSH dùng được.

3.2. Kiểm tra PHP CLI

which php
php -v
php -m | head

3.3. Kiểm tra công cụ nén file (tar, gzip, zip)

which tar
which gzip
which zip
which unzip

Test nén thử 1 folder nhỏ:

mkdir -p ~/backup_test
echo "test backup" > ~/backup_test/readme.txt

tar -czf ~/backup_test.tar.gz -C ~/ backup_test
ls -lh ~/backup_test.tar.gz

Nếu tạo được backup_test.tar.gz → sau này có thể nén toàn bộ public_html.

3.4. Kiểm tra mysqldump để backup MySQL

which mysqldump
mysqldump --version

Nếu có, test dump 1 DB nhỏ:

mysqldump -h localhost -u DB_USERNAME -p DB_NAME > ~/db_test_backup.sql
ls -lh ~/db_test_backup.sql
head -n 20 ~/db_test_backup.sql

Nếu không có mysqldump hoặc bị chặn, bản PHP sẽ tự dump DB bằng mysqli, không cần binary này.

3.5. Kiểm tra công cụ upload: curl / wget

which curl
curl --version

which wget
wget --version

Test mạng:

curl -I https://google.com
wget -qO- https://google.com | head

Chỉ cần curl là đủ cho Telegram & một số API.

3.6. Kiểm tra chạy script PHP từ CLI

Tạo folder script riêng:

mkdir -p ~/scripts
cd ~/scripts

Tạo file test_cron.php:

cat > test_cron.php << 'EOF'
<?php
$file = __DIR__ . '/cron_log.txt';
$date = date('Y-m-d H:i:s');
file_put_contents($file, "Cron test run at: {$date}\n", FILE_APPEND);
echo "Cron test OK at {$date}\n";
EOF

Chạy thử:

php ~/scripts/test_cron.php
ls -lh ~/scripts/cron_log.txt
cat ~/scripts/cron_log.txt

Nếu log được tạo → PHP CLI OK, cron sau này chỉ cần gọi lại lệnh này.

3.7. Checklist nhanh trước khi set cron backup

  1. php -v → PHP CLI OK.
  2. tar -czf ... → nén file OK.
  3. mysqldump --version → có (nếu dùng Bash script).
  4. curl --version → có.
  5. (Nếu dùng rclone/aws-cli) → rclone version / aws --version.
  6. php ~/scripts/test_cron.php → ghi log OK.

Nếu tất cả ổn → sẵn sàng triển khai script backup.

Để tiện dùng binary aws, rclone trong home, thêm vào ~/.bashrc:

echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

4. Script Bash – backup_all_stores.sh

Tất cả phần này chỉ cần chạy script cài đặt này nó sẽ cài đặt toàn bộ môi trường và script được tải về hosting/vps:

bash <(curl -s https://anhnnp.pages.dev/data/script-batch/install_wp_backup_env.sh)

File này sẽ tự động:

Dùng cho VPS / hosting cho chạy binary (aws, rclone, tar, pigz, mysqldump…).

⚠️ Lưu ý:

4.1. Cài AWS CLI (local user, không cần root)

Bước 1 – Tạo thư mục chứa installer

mkdir -p ~/tools
cd ~/tools

Bước 2 – Tải AWS CLI v2

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip

Bước 3 – Cài vào HOME

./aws/install --bin-dir ~/bin --install-dir ~/aws-cli

Nếu ~/bin chưa tồn tại:

mkdir -p ~/bin

Bước 4 – Add AWS CLI vào PATH

Trong ~/.bashrc:

echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

Bước 5 – Kiểm tra

aws --version

Bước 6 – Cấu hình AWS CLI

aws configure

Nhập:

Test:

aws s3 ls

Nếu thấy list bucket → OK.

Tạo bucket sites-backup và dùng prefix wp-backups/. Script sẽ dùng storage class:

AWS_S3_STORAGE_CLASS="DEEP_ARCHIVE"

Một số storage class hay dùng:

4.2. Cài rclone để upload Google Drive

Bước 1 – Install rclone trên server

cd ~
curl -O https://downloads.rclone.org/rclone-current-linux-amd64.zip
unzip rclone-current-linux-amd64.zip
cd rclone-*-linux-amd64
mkdir -p ~/bin
cp rclone ~/bin
chmod 755 ~/bin/rclone

Thêm PATH nếu chưa có:

echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

Kiểm tra:

rclone version

Bước 2 – Config rclone (trên máy local)

Do shared hosting không mở browser, nên chuẩn là:

File rclone.conf nằm tại:

Copy nội dung [gdrive] đó.

Bước 3 – Copy config lên server

mkdir -p ~/.config/rclone
vi ~/.config/rclone/rclone.conf

Paste nội dung đã copy, lưu file.

Test:

rclone lsd gdrive:
rclone mkdir gdrive:wp-backups

Upload test:

echo "hello" > ~/test.txt
rclone copy ~/test.txt gdrive:wp-backups/test
aws s3 cp ~/test.txt s3://sites-backup/test.txt

Nếu cả 2 đều OK → môi trường remote sẵn sàng.

4.3. Chuẩn bị script & PATH cho cron

Đảm bảo ~/.bashrc có:

export PATH="$HOME/bin:$PATH"

~/.bash_profile tự load ~/.bashrc:

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

Tạo folder:

cd /home/USER

mkdir -p scripts
mkdir -p backups
mkdir -p logs

Copy file backup_all_stores.sh vào:

/home/USER/scripts/backup_all_stores.sh
chmod +x /home/USER/scripts/backup_all_stores.sh

Mở file và chỉnh:

BASE_DIR="/home/USER"

STORES=(
  "domain1.com"
  "domain2.com"
)

AWS_S3_BUCKET="sites-backup"
AWS_S3_PREFIX="wp-backups"
AWS_S3_STORAGE_CLASS="DEEP_ARCHIVE"

RCLONE_REMOTE_GDRIVE="gdrive"
RCLONE_GDRIVE_PATH="wp-backups"

RETENTION_DAYS=7
LOG_RETENTION_DAYS=30

EXCLUDED_DIR_PATTERNS=(
  "aiowps_backups"
  "wp-cloudflare-super-page-cache"
  "litespeed"
)

ENABLE_TELEGRAM=true
TELEGRAM_BOT_TOKEN="YOUR_BOT_TOKEN"
TELEGRAM_CHAT_ID="YOUR_CHAT_ID"
TELEGRAM_MODE="full"   # hoặc "error" / "off"

Script sẽ tự:

4.4. Test chạy Bash script

bash /home/USER/scripts/backup_all_stores.sh

Kiểm tra:

4.5. Thiết lập cron cho Bash script

Xác định timezone server

date
php -r 'echo "PHP time: ", date("c"), "\n";'
timedatectl 2>/dev/null

Nếu date ≈ UTC → server chạy UTC. Nếu date giống giờ VN (UTC+7) → server Asia/Bangkok/Ho Chi Minh.

Chọn giờ backup

Gợi ý 08:00 UTC (≈ 15:00 VN):

Nếu server = UTC, dòng cron:

0 8 * * * /bin/bash /home/USER/scripts/backup_all_stores.sh >/home/USER/logs/cron_backup.log 2>&1

Nếu server = UTC+7 (VN):

0 15 * * * /bin/bash /home/USER/scripts/backup_all_stores.sh >/home/USER/logs/cron_backup.log 2>&1

Thiết lập:

crontab -e
# thêm 1 dòng:
0 8 * * * /bin/bash /home/USER/scripts/backup_all_stores.sh >/home/USER/logs/cron_backup.log 2>&1

Kiểm tra lại:

crontab -l

Nếu hosting không cho crontab -e, dùng Cron Jobs trong hPanel/cPanel với command tương tự.

5. Script PHP – backup_all_stores.php

Dùng khi hosting chặn aws-cli, rclone, tar, mysqldump… nhưng cho chạy PHP CLI và cho cài Composer.

5.1. Cài Composer & PHP libraries

Trong thư mục:

mkdir -p /home/USER/scripts-php-backup
cd /home/USER/scripts-php-backup

composer require aws/aws-sdk-php:^3.0 google/apiclient:^2.0

Đặt file backup_all_stores.php vào /home/USER/scripts-php-backup.

5.2. Google Drive token (lấy lại từ rclone)

Từ ~/.config/rclone/rclone.conf (Linux) hoặc C:\Users\<you>\AppData\Roaming\rclone\rclone.conf (Windows), tìm section:

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

Tạo file /home/USER/scripts-php-backup/gdrive_token.json:

{
  "access_token": "....",
  "refresh_token": "....",
  "expiry": "2025-11-21T23:18:48.4449677+07:00"
}

Script PHP sẽ:

Trên Google Drive, tạo folder backup (hoặc wp-backups) và lấy folder ID:

5.3. Chỉnh config trong PHP script

Trong backup_all_stores.php, chỉnh các biến:

$BASE_DIR     = '/home/USER';
$DOMAINS_BASE = $BASE_DIR . '/domains';
$BACKUP_BASE  = $BASE_DIR . '/backups-php';
$LOG_DIR      = $BASE_DIR . '/logs';

$STORES = [
    'domain1.com',
    'domain2.com',
];

$EXCLUDED_DIR_PATTERNS = [
    'aiowps_backups',
    'wp-cloudflare-super-page-cache',
    'litespeed',
];

$AWS_S3_BUCKET        = 'sites-backup';
$AWS_S3_PREFIX        = 'wp-backups';
$AWS_S3_REGION        = 'ap-southeast-1';
$AWS_S3_KEY           = 'YOUR_AWS_KEY';
$AWS_S3_SECRET        = 'YOUR_AWS_SECRET';
$AWS_S3_STORAGE_CLASS = 'DEEP_ARCHIVE';

$GDRIVE_CLIENT_ID      = 'YOUR_GOOGLE_CLIENT_ID';
$GDRIVE_CLIENT_SECRET  = 'YOUR_GOOGLE_CLIENT_SECRET';
$GDRIVE_TOKEN_FILE     = __DIR__ . '/gdrive_token.json';
$GDRIVE_ROOT_FOLDER_ID = '11HZ0giOqEw6wyy2ylI3GcBmSm5ZQ1YZU'; // ví dụ

$ENABLE_TELEGRAM    = true;
$TELEGRAM_BOT_TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN';
$TELEGRAM_CHAT_ID   = 'YOUR_CHAT_ID';
$TELEGRAM_MODE      = 'full';   // 'error' hoặc 'off'

5.4. Cách hoạt động của script PHP

Script thực hiện:

  1. Loop qua danh sách $STORES.

  2. Với mỗi store:

    • Đọc wp-config.php trong domains/<domain>/public_html.
    • Parse DB_NAME, DB_USER, DB_PASSWORD, DB_HOST.
  3. Dump database:

    • Kết nối mysqli.
    • Ghi header: SET NAMES, foreign_key_checks, sql_mode
    • SHOW TABLES → lấy list bảng.
    • Với mỗi bảng:
      • SHOW CREATE TABLE → ghi cấu trúc.
      • SELECT COUNT(*) → tổng số row.
      • For loop theo chunk LIMIT offset, chunkSize (ví dụ 500):
        • Ghi INSERT multi-row → (…), (…), … vào file .sql.gz.
  4. Zip files:

    • Dùng ZipArchive.
    • Duyệt đệ quy public_html.
    • Bỏ qua path chứa chuỗi trong $EXCLUDED_DIR_PATTERNS.
    • Ghi file .zip mỗi store.
  5. Upload S3:

    • AWS SDK for PHP, putObject từng file trong backups-php/YYYY-MM-DD.
    • Storage class DEEP_ARCHIVE (rất rẻ).
  6. Upload Google Drive:

    • Google API PHP client + token OAuth.
    • Tìm/ tạo folder theo ngày YYYY-MM-DD bên trong $GDRIVE_ROOT_FOLDER_ID.
    • Upload từng file backup vào đó.
  7. Retention:

    • Xóa folder backup local cũ hơn RETENTION_DAYS.
    • Xóa folder ngày cũ trên S3 và Google Drive (đặt tên dạng YYYY-MM-DD).
  8. Tính tổng size:

    • S3: listObjectsV2, cộng Size.
    • GDrive: duyệt folder con, cộng size các file.
  9. Telegram summary:

    • Gửi báo cáo dạng:WP PHP Backup Report Date: 2025-11-23 Disk usage: …

Backup status: OK / ERROR S3 upload: OK/ERROR GDrive upload: OK/ERROR S3 retention: … GDrive retention: …

5.5. Test script PHP

Chạy bằng CLI:

php -d display_errors=1 /home/USER/scripts-php-backup/backup_all_stores.php

Kiểm tra:

Nếu có lỗi Google Drive quota (service account) hoặc token, chỉ cần sửa token / root folder ID là xong.

5.6. Cron cho PHP script

Giả sử server UTC, muốn chạy 08:15 UTC mỗi ngày:

crontab -e
15 8 * * * /usr/bin/php /home/USER/scripts-php-backup/backup_all_stores.php >/home/USER/logs/cron_backup_php.log 2>&1

Nếu server UTC+7, muốn chạy 15:15 (giờ VN):

15 15 * * * /usr/bin/php /home/USER/scripts-php-backup/backup_all_stores.php >/home/USER/logs/cron_backup_php.log 2>&1

Trên cùng 1 server nên chọn 1 trong 2 giải pháp (Bash hoặc PHP) làm chính để tránh backup trùng.

6. Restore từ backup

6.1. Restore files

Bash script (tar.gz)

cd /home/USER/domains/domain1.com/public_html
tar -xzf /path/to/files_store1_2025-11-21.tar.gz

PHP script (.zip)

6.2. Restore database

gunzip < db_store1_2025-11-21.sql.gz | mysql -h DB_HOST -u DB_USER -p DB_NAME

Hoặc:

6.3. Nếu backup nằm trong S3 Glacier Deep Archive

7. Troubleshooting nhanh

Kết luận: Sau khi bạn thiết lập xong 2 script backup_all_stores.sh (cho VPS/hosting mạnh) và backup_all_stores.php (cho shared hosting khó chịu), mỗi lần mua hosting/VPS mới bạn chỉ cần:

  1. Tạo cấu trúc folder chuẩn /home/USER/domains, backups, backups-php, logs, scripts, scripts-php-backup.
  2. Cài aws-cli + rclone (nếu dùng Bash) hoặc Composer + PHP SDK (nếu dùng PHP).
  3. Copy 2 file script + chỉnh vài biến config (USER, domain, bucket, Drive ID, Telegram).
  4. Thêm cron chạy hàng ngày.

Toàn bộ hệ thống WordPress multi store của bạn sẽ được backup tự động, lưu song song ở S3 Glacier Deep ArchiveGoogle Drive, kèm log + Telegram report mỗi ngày. Bạn chỉ cần lo bán hàng, còn dữ liệu để hệ thống tự giữ giúp.

Nguồn tài nguyên:

Trải nghiệm tốt nhất từ thực hành — Anh Nguyen

← Danh sách bài viết
  • Triển khai Blog Astro + CI/CD Đa Nền Tảng

    Triển khai Blog Astro + CI/CD Đa Nền Tảng

    Bài viết mình tổng hợp toàn bộ quá trình triển khai blog cá nhân với Astro (sử dụng Sveltia CMS), multi deploy, CI/CD GitHub Actions, cache busting, multi host (GitHub Pages + Vercel + Render + Netlify + DO + Cloudflare + Neocities + Surge + Wasmer)… từ A → Z.

  • So Sánh toàn diện LocalWP, MAMP, Laragon, XAMPP và WAMP Server Trên Windows

    So Sánh toàn diện LocalWP, MAMP, Laragon, XAMPP và WAMP Server Trên Windows

    Bạn đang tìm môi trường local để phát triển PHP hoặc WordPress trên Windows? Bài viết này sẽ giúp bạn hiểu rõ sự khác biệt giữa LocalWP, Laragon, MAMP, XAMPP, và WAMP Server – để chọn ra công cụ tối ưu nhất cho quy trình làm việc của bạn.

  • Công cụ mã nguồn mở kích hoạt Windows và Office kèm tính năng debug nâng cao

    Công cụ mã nguồn mở kích hoạt Windows và Office kèm tính năng debug nâng cao

    Hỗ trợ các phương thức kích hoạt như HWID, Ohook, KMS38 và Online KMS. Công cụ này cung cấp khả năng xử lý sự cố mạnh mẽ và kích hoạt sản phẩm Microsoft hiệu quả, đáp ứng nhiều nhu cầu người dùng theo cách linh hoạt, có thể tùy biến.

  • Plugin tối ưu ảnh tốt nhất cho Wordpress là gì? Optimole vs ShortPixel vs Imagify vs EWWW vs Smush

    Plugin tối ưu ảnh tốt nhất cho Wordpress là gì? Optimole vs ShortPixel vs Imagify vs EWWW vs Smush

    Đâu là plugin tối ưu ảnh tốt nhất cho Wordpress WooCommerce & blog nhiều ảnh? So sánh thực chiến Optimole, ShortPixel, Imagify, EWWW, Smush - Mình sẽ đi từ phương pháp test → kết quả → phân tích từng plugin → xếp hạng & khuyến nghị theo use case (online store, blog nhiều ảnh).

  • Những cách đơn giản để kích hoạt Windows 11 miễn phí mà không cần product key

    Những cách đơn giản để kích hoạt Windows 11 miễn phí mà không cần product key

    Chia sẻ kích hoạt Windows 11 bằng key KMS client miễn phí gồm các bước hoàn toàn giống với hướng dẫn cách kích hoạt Windows 10 miễn phí, chỉ khác là lần này mình thực hiện trên Windows 11.

  • Miễn phí 9 nền tảng headless CMS lưu trữ trên Git cho các Blog website đơn giản

    Miễn phí 9 nền tảng headless CMS lưu trữ  trên Git cho các Blog website đơn giản

    Đây là một chủ đề cực kỳ hữu ích cho các dev hiện đại, đặc biệt là những ai đang chuyển từ WordPress sang mô hình headless CMS. Nếu CMS truyền thống là tất cả trong một (cả backend lẫn frontend), thì headless CMS chỉ tập trung vào phần quản lý nội dung (backend), còn phần hiển thị (frontend) sẽ do bạn tự do chọn framework hoặc build theo ý muốn.