Shell腳本實(shí)現(xiàn)自動(dòng)備份網(wǎng)站和數(shù)據(jù)庫(kù)并上傳到云存儲(chǔ)
1. 備份方案概述
在本教程中,我們將創(chuàng)建一個(gè)完整的自動(dòng)化備份系統(tǒng),用于備份網(wǎng)站文件和數(shù)據(jù)庫(kù),并將備份文件上傳到云存儲(chǔ)。該系統(tǒng)包含錯(cuò)誤處理、日志記錄和通知功能,適合生產(chǎn)環(huán)境使用。

2. 環(huán)境準(zhǔn)備和依賴安裝
2.1 系統(tǒng)要求檢查
首先創(chuàng)建環(huán)境檢查腳本:
#!/bin/bash
# check_environment.sh
echo "檢查系統(tǒng)環(huán)境..."
# 檢查操作系統(tǒng)
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
echo "操作系統(tǒng): $OS $VER"
else
echo "警告: 無(wú)法檢測(cè)操作系統(tǒng)版本"
fi
# 檢查磁盤空間
echo "磁盤空間信息:"
df -h / /tmp /var
# 檢查必要的工具
required_tools=("tar" "gzip" "mysql" "pg_dump" "curl")
for tool in "${required_tools[@]}"; do
if command -v $tool &> /dev/null; then
echo "? $tool 已安裝"
else
echo "? $tool 未安裝"
fi
done
# 檢查云存儲(chǔ)工具
cloud_tools=("aws" "gsutil" "ossutil")
for tool in "${cloud_tools[@]}"; do
if command -v $tool &> /dev/null; then
echo "? $tool 已安裝"
else
echo "? $tool 未安裝 (可選)"
fi
done
2.2 安裝必要的軟件包
根據(jù)不同的Linux發(fā)行版安裝所需軟件:
#!/bin/bash
# install_dependencies.sh
echo "安裝備份所需的軟件包..."
# 檢測(cè)發(fā)行版
if [ -f /etc/redhat-release ]; then
# CentOS/RHEL
sudo yum update -y
sudo yum install -y tar gzip mysql-server postgresql curl python3-pip
elif [ -f /etc/debian_version ]; then
# Ubuntu/Debian
sudo apt update
sudo apt install -y tar gzip mysql-client postgresql-client curl python3-pip
else
echo "不支持的Linux發(fā)行版"
exit 1
fi
# 安裝云存儲(chǔ)CLI工具
echo "安裝AWS CLI..."
pip3 install awscli --upgrade --user
echo "安裝Google Cloud SDK..."
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
echo "安裝阿里云OSS工具..."
wget -O ossutil64 https://gosspublic.alicdn.com/ossutil/1.7.14/ossutil64
chmod 755 ossutil64
sudo mv ossutil64 /usr/local/bin/ossutil
3. 配置文件設(shè)置
創(chuàng)建主配置文件:
#!/bin/bash
# config/backup.conf
# 備份配置
BACKUP_DIR="/opt/backups"
LOG_DIR="/var/log/backups"
RETENTION_DAYS=30
COMPRESSION_LEVEL=6
# 網(wǎng)站文件配置
WEB_ROOT="/var/www/html"
EXCLUDE_PATTERNS=("*.log" "*.tmp" "cache/*" "tmp/*")
# 數(shù)據(jù)庫(kù)配置
# MySQL
MYSQL_HOST="localhost"
MYSQL_PORT="3306"
MYSQL_USER="backup_user"
MYSQL_PASSWORD="your_secure_password"
MYSQL_DATABASES=("wordpress" "mydatabase" "application_db")
# PostgreSQL
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="backup_user"
PG_PASSWORD="your_secure_password"
PG_DATABASES=("app_production" "analytics_db")
# 云存儲(chǔ)配置
# AWS S3
AWS_BUCKET="my-backup-bucket"
AWS_REGION="us-east-1"
# Google Cloud Storage
GCS_BUCKET="my-backup-bucket"
# 阿里云OSS
OSS_BUCKET="my-backup-bucket"
OSS_ENDPOINT="oss-cn-hangzhou.aliyuncs.com"
# 通知配置
EMAIL_RECIPIENT="admin@example.com"
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/your/webhook/url"
創(chuàng)建數(shù)據(jù)庫(kù)用戶配置腳本:
#!/bin/bash # setup_database_users.sh echo "設(shè)置數(shù)據(jù)庫(kù)備份用戶..." # MySQL備份用戶設(shè)置 mysql -u root -p <<EOF -- 創(chuàng)建備份用戶 CREATE USER IF NOT EXISTS 'backup_user'@'localhost' IDENTIFIED BY 'your_secure_password'; -- 授予必要權(quán)限 GRANT SELECT, LOCK TABLES, SHOW VIEW, PROCESS ON *.* TO 'backup_user'@'localhost'; -- 刷新權(quán)限 FLUSH PRIVILEGES; -- 顯示用戶權(quán)限 SHOW GRANTS FOR 'backup_user'@'localhost'; EOF # PostgreSQL備份用戶設(shè)置 sudo -u postgres psql <<EOF -- 創(chuàng)建備份用戶 CREATE USER backup_user WITH PASSWORD 'your_secure_password'; -- 授予必要權(quán)限 ALTER USER backup_user WITH SUPERUSER; -- 顯示用戶信息 \du backup_user EOF echo "數(shù)據(jù)庫(kù)備份用戶設(shè)置完成"
4. 核心備份腳本
創(chuàng)建主備份腳本:
#!/bin/bash
# website_backup.sh
# 加載配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/config/backup.conf"
# 設(shè)置變量
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${TIMESTAMP}"
BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}"
LOG_FILE="${LOG_DIR}/backup_${TIMESTAMP}.log"
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函數(shù)
log() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE"
}
log_info() {
log "INFO" "${BLUE}$1${NC}"
}
log_success() {
log "SUCCESS" "${GREEN}$1${NC}"
}
log_warning() {
log "WARNING" "${YELLOW}$1${NC}"
}
log_error() {
log "ERROR" "${RED}$1${NC}"
}
# 錯(cuò)誤處理函數(shù)
error_exit() {
log_error "$1"
send_notification "備份失敗" "$1"
exit 1
}
# 通知函數(shù)
send_notification() {
local subject=$1
local message=$2
# 郵件通知
if command -v mail &> /dev/null && [ -n "$EMAIL_RECIPIENT" ]; then
echo "$message" | mail -s "Backup Alert: $subject" "$EMAIL_RECIPIENT"
fi
# Slack通知
if command -v curl &> /dev/null && [ -n "$SLACK_WEBHOOK_URL" ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"*Backup Alert*: $subject\n$message\"}" \
"$SLACK_WEBHOOK_URL" > /dev/null 2>&1
fi
}
# 初始化備份環(huán)境
init_backup() {
log_info "初始化備份環(huán)境..."
# 創(chuàng)建目錄
mkdir -p "$BACKUP_DIR" "$LOG_DIR" "$BACKUP_PATH"
# 檢查目錄權(quán)限
if [ ! -w "$BACKUP_DIR" ]; then
error_exit "備份目錄不可寫: $BACKUP_DIR"
fi
if [ ! -r "$WEB_ROOT" ]; then
error_exit "網(wǎng)站目錄不可讀: $WEB_ROOT"
fi
log_success "備份環(huán)境初始化完成"
}
# 備份網(wǎng)站文件
backup_website_files() {
log_info "開(kāi)始備份網(wǎng)站文件..."
local exclude_args=()
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
exclude_args+=(--exclude="$pattern")
done
cd "$WEB_ROOT" || error_exit "無(wú)法進(jìn)入網(wǎng)站目錄: $WEB_ROOT"
# 創(chuàng)建文件列表
find . -type f > "${BACKUP_PATH}/file_list.txt"
# 打包網(wǎng)站文件
if tar czf "${BACKUP_PATH}/website_files.tar.gz" \
"${exclude_args[@]}" \
. > /dev/null 2>&1; then
local size=$(du -h "${BACKUP_PATH}/website_files.tar.gz" | cut -f1)
log_success "網(wǎng)站文件備份完成: ${size}"
else
error_exit "網(wǎng)站文件備份失敗"
fi
}
# 備份MySQL數(shù)據(jù)庫(kù)
backup_mysql_databases() {
log_info "開(kāi)始備份MySQL數(shù)據(jù)庫(kù)..."
# 測(cè)試MySQL連接
if ! mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SELECT 1" > /dev/null 2>&1; then
log_warning "MySQL連接失敗,跳過(guò)MySQL備份"
return 1
fi
# 獲取數(shù)據(jù)庫(kù)列表
local databases
databases=$(mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")
local success_count=0
local total_count=0
for db in $databases; do
# 檢查數(shù)據(jù)庫(kù)是否在配置列表中
if [[ " ${MYSQL_DATABASES[@]} " =~ " ${db} " ]] || [ ${#MYSQL_DATABASES[@]} -eq 0 ]; then
((total_count++))
log_info "備份MySQL數(shù)據(jù)庫(kù): $db"
if mysqldump -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" \
--single-transaction \
--routines \
--triggers \
"$db" > "${BACKUP_PATH}/mysql_${db}.sql" 2>> "$LOG_FILE"; then
# 壓縮備份文件
gzip "${BACKUP_PATH}/mysql_${db}.sql"
((success_count++))
log_success "MySQL數(shù)據(jù)庫(kù)備份完成: $db"
else
log_error "MySQL數(shù)據(jù)庫(kù)備份失敗: $db"
fi
fi
done
log_success "MySQL備份完成: ${success_count}/${total_count} 個(gè)數(shù)據(jù)庫(kù)"
}
# 備份PostgreSQL數(shù)據(jù)庫(kù)
backup_postgresql_databases() {
log_info "開(kāi)始備份PostgreSQL數(shù)據(jù)庫(kù)..."
# 設(shè)置密碼
export PGPASSWORD="$PG_PASSWORD"
# 測(cè)試PostgreSQL連接
if ! psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d postgres -c "SELECT 1" > /dev/null 2>&1; then
log_warning "PostgreSQL連接失敗,跳過(guò)PostgreSQL備份"
return 1
fi
local success_count=0
local total_count=0
for db in "${PG_DATABASES[@]}"; do
((total_count++))
log_info "備份PostgreSQL數(shù)據(jù)庫(kù): $db"
if pg_dump -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" \
--verbose \
--no-password \
"$db" > "${BACKUP_PATH}/pgsql_${db}.sql" 2>> "$LOG_FILE"; then
# 壓縮備份文件
gzip "${BACKUP_PATH}/pgsql_${db}.sql"
((success_count++))
log_success "PostgreSQL數(shù)據(jù)庫(kù)備份完成: $db"
else
log_error "PostgreSQL數(shù)據(jù)庫(kù)備份失敗: $db"
fi
done
log_success "PostgreSQL備份完成: ${success_count}/${total_count} 個(gè)數(shù)據(jù)庫(kù)"
}
# 創(chuàng)建備份清單
create_backup_manifest() {
log_info "創(chuàng)建備份清單..."
cat > "${BACKUP_PATH}/manifest.json" << EOF
{
"backup_name": "${BACKUP_NAME}",
"timestamp": "${TIMESTAMP}",
"created_at": "$(date -Iseconds)",
"components": {
"website_files": "$(if [ -f "${BACKUP_PATH}/website_files.tar.gz" ]; then echo "true"; else echo "false"; fi)",
"mysql_databases": "$(ls "${BACKUP_PATH}"/mysql_*.sql.gz 2>/dev/null | wc -l)",
"postgresql_databases": "$(ls "${BACKUP_PATH}"/pgsql_*.sql.gz 2>/dev/null | wc -l)"
},
"system_info": {
"hostname": "$(hostname)",
"disk_usage": "$(df -h / | awk 'NR==2 {print $5}')"
}
}
EOF
log_success "備份清單創(chuàng)建完成"
}
# 壓縮備份文件
compress_backup() {
log_info "壓縮備份文件..."
cd "$BACKUP_DIR" || error_exit "無(wú)法進(jìn)入備份目錄"
if tar czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME" > /dev/null 2>&1; then
local final_size=$(du -h "${BACKUP_NAME}.tar.gz" | cut -f1)
log_success "備份文件壓縮完成: ${final_size}"
# 清理臨時(shí)文件
rm -rf "$BACKUP_PATH"
else
error_exit "備份文件壓縮失敗"
fi
}
# 上傳到云存儲(chǔ)
upload_to_cloud() {
log_info "開(kāi)始上傳到云存儲(chǔ)..."
local backup_file="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
# 上傳到AWS S3
if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
log_info "上傳到AWS S3..."
if aws s3 cp "$backup_file" "s3://${AWS_BUCKET}/${BACKUP_NAME}.tar.gz" --region "$AWS_REGION" >> "$LOG_FILE" 2>&1; then
log_success "上傳到AWS S3完成"
else
log_error "上傳到AWS S3失敗"
fi
fi
# 上傳到Google Cloud Storage
if command -v gsutil &> /dev/null && [ -n "$GCS_BUCKET" ]; then
log_info "上傳到Google Cloud Storage..."
if gsutil cp "$backup_file" "gs://${GCS_BUCKET}/${BACKUP_NAME}.tar.gz" >> "$LOG_FILE" 2>&1; then
log_success "上傳到Google Cloud Storage完成"
else
log_error "上傳到Google Cloud Storage失敗"
fi
fi
# 上傳到阿里云OSS
if command -v ossutil &> /dev/null && [ -n "$OSS_BUCKET" ]; then
log_info "上傳到阿里云OSS..."
if ossutil cp "$backup_file" "oss://${OSS_BUCKET}/${BACKUP_NAME}.tar.gz" -e "$OSS_ENDPOINT" >> "$LOG_FILE" 2>&1; then
log_success "上傳到阿里云OSS完成"
else
log_error "上傳到阿里云OSS失敗"
fi
fi
}
# 清理舊備份
cleanup_old_backups() {
log_info "清理舊備份文件..."
local local_count=0
local cloud_count=0
# 清理本地備份
find "$BACKUP_DIR" -name "backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS | while read -r file; do
rm -f "$file"
((local_count++))
done
# 清理云存儲(chǔ)備份 (AWS S3示例)
if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
aws s3 ls "s3://${AWS_BUCKET}/" | grep "backup_" | while read -r date time size file; do
local backup_date=$(echo "$file" | cut -d'_' -f2)
local current_ts=$(date +%s)
local backup_ts=$(date -d "${backup_date:0:8} ${backup_date:9:2}:${backup_date:11:2}:${backup_date:13:2}" +%s 2>/dev/null || echo 0)
local age_days=$(( (current_ts - backup_ts) / 86400 ))
if [ $age_days -gt $RETENTION_DAYS ]; then
aws s3 rm "s3://${AWS_BUCKET}/$file"
((cloud_count++))
fi
done
fi
log_success "清理完成: 本地${local_count}個(gè), 云存儲(chǔ)${cloud_count}個(gè)備份文件"
}
# 生成備份報(bào)告
generate_report() {
local end_time=$(date +%s)
local duration=$((end_time - ${START_TIME}))
cat > "${BACKUP_DIR}/backup_report_${TIMESTAMP}.txt" << EOF
備份報(bào)告
========
備份名稱: ${BACKUP_NAME}
開(kāi)始時(shí)間: $(date -d @${START_TIME} '+%Y-%m-%d %H:%M:%S')
結(jié)束時(shí)間: $(date -d @${end_time} '+%Y-%m-%d %H:%M:%S')
持續(xù)時(shí)間: ${duration} 秒
備份組件:
- 網(wǎng)站文件: $(if [ -f "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" ]; then echo "成功"; else echo "失敗"; fi)
- MySQL數(shù)據(jù)庫(kù): $(ls "${BACKUP_DIR}" | grep "mysql_.*\.sql.gz" | wc -l) 個(gè)
- PostgreSQL數(shù)據(jù)庫(kù): $(ls "${BACKUP_DIR}" | grep "pgsql_.*\.sql.gz" | wc -l) 個(gè)
存儲(chǔ)信息:
- 本地備份: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz
- 云存儲(chǔ): $(if [ -n "$AWS_BUCKET" ] || [ -n "$GCS_BUCKET" ] || [ -n "$OSS_BUCKET" ]; then echo "已上傳"; else echo "未配置"; fi)
錯(cuò)誤日志: $LOG_FILE
EOF
}
# 主函數(shù)
main() {
START_TIME=$(date +%s)
log_info "=== 開(kāi)始備份任務(wù) ==="
# 執(zhí)行備份流程
init_backup
backup_website_files
backup_mysql_databases
backup_postgresql_databases
create_backup_manifest
compress_backup
upload_to_cloud
cleanup_old_backups
# 生成報(bào)告
generate_report
local end_time=$(date +%s)
local duration=$((end_time - START_TIME))
log_success "=== 備份任務(wù)完成 ==="
log_success "總耗時(shí): ${duration} 秒"
# 發(fā)送成功通知
send_notification "備份完成" "備份任務(wù) ${BACKUP_NAME} 已完成,耗時(shí) ${duration} 秒"
}
# 信號(hào)處理
trap 'log_error "備份被用戶中斷"; exit 1' INT TERM
# 執(zhí)行主函數(shù)
main "$@"
5. 自動(dòng)化部署腳本
創(chuàng)建安裝和部署腳本:
#!/bin/bash
# deploy_backup_system.sh
set -e
echo "開(kāi)始部署自動(dòng)化備份系統(tǒng)..."
# 創(chuàng)建目錄結(jié)構(gòu)
echo "創(chuàng)建目錄結(jié)構(gòu)..."
sudo mkdir -p /opt/backups/{config,scripts,logs}
sudo mkdir -p /var/log/backups
# 復(fù)制腳本文件
echo "復(fù)制腳本文件..."
sudo cp website_backup.sh /opt/backups/scripts/
sudo cp config/backup.conf /opt/backups/config/
sudo cp check_environment.sh /opt/backups/scripts/
# 設(shè)置權(quán)限
echo "設(shè)置權(quán)限..."
sudo chmod +x /opt/backups/scripts/*.sh
sudo chmod 600 /opt/backups/config/backup.conf
# 設(shè)置配置文件權(quán)限
sudo chown root:root /opt/backups/config/backup.conf
sudo chmod 400 /opt/backups/config/backup.conf
# 創(chuàng)建備份用戶
echo "創(chuàng)建備份用戶..."
if ! id "backupuser" &>/dev/null; then
sudo useradd -r -s /bin/bash -d /opt/backups backupuser
fi
# 設(shè)置目錄所有權(quán)
sudo chown -R backupuser:backupuser /opt/backups
sudo chown -R backupuser:backupuser /var/log/backups
# 配置日志輪轉(zhuǎn)
echo "配置日志輪轉(zhuǎn)..."
sudo tee /etc/logrotate.d/backups > /dev/null <<EOF
/var/log/backups/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 backupuser backupuser
}
EOF
echo "部署完成!"
6. 定時(shí)任務(wù)配置
創(chuàng)建crontab配置:
#!/bin/bash # setup_cron.sh echo "配置定時(shí)任務(wù)..." # 備份crontab sudo cp /etc/crontab /etc/crontab.backup.$(date +%Y%m%d) # 添加每日備份任務(wù) (凌晨2點(diǎn)) echo "0 2 * * * backupuser /opt/backups/scripts/website_backup.sh >> /var/log/backups/cron.log 2>&1" | sudo tee -a /etc/crontab # 添加每周完整備份 (周日凌晨1點(diǎn)) echo "0 1 * * 0 backupuser /opt/backups/scripts/website_backup.sh >> /var/log/backups/cron.log 2>&1" | sudo tee -a /etc/crontab # 添加監(jiān)控檢查 (每小時(shí)) echo "0 * * * * backupuser /opt/backups/scripts/check_environment.sh >> /var/log/backups/monitor.log 2>&1" | sudo tee -a /etc/crontab # 重新加載cron sudo systemctl reload crond echo "定時(shí)任務(wù)配置完成" echo "當(dāng)前crontab配置:" sudo crontab -l
7. 監(jiān)控和驗(yàn)證腳本
創(chuàng)建備份驗(yàn)證腳本:
#!/bin/bash
# verify_backup.sh
source /opt/backups/config/backup.conf
echo "開(kāi)始驗(yàn)證備份完整性..."
# 檢查最新備份文件
latest_backup=$(ls -t ${BACKUP_DIR}/backup_*.tar.gz 2>/dev/null | head -1)
if [ -z "$latest_backup" ]; then
echo "錯(cuò)誤: 未找到備份文件"
exit 1
fi
echo "驗(yàn)證備份文件: $latest_backup"
# 檢查文件大小
file_size=$(du -h "$latest_backup" | cut -f1)
echo "備份文件大小: $file_size"
# 檢查文件完整性
if tar tzf "$latest_backup" > /dev/null 2>&1; then
echo "? 備份文件完整性檢查通過(guò)"
else
echo "? 備份文件損壞"
exit 1
fi
# 檢查備份內(nèi)容
echo "備份內(nèi)容:"
tar tzf "$latest_backup" | head -10
# 檢查云存儲(chǔ)備份
if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
if aws s3 ls "s3://${AWS_BUCKET}/" | grep -q "$(basename $latest_backup)"; then
echo "? 云存儲(chǔ)備份驗(yàn)證通過(guò)"
else
echo "? 云存儲(chǔ)備份不存在"
fi
fi
echo "備份驗(yàn)證完成"
8. 恢復(fù)腳本
創(chuàng)建數(shù)據(jù)恢復(fù)腳本:
#!/bin/bash
# restore_backup.sh
source /opt/backups/config/backup.conf
show_usage() {
echo "使用方法: $0 [選項(xiàng)]"
echo "選項(xiàng):"
echo " -f, --file FILE 指定備份文件"
echo " -d, --date DATE 按日期恢復(fù) (格式: YYYYMMDD_HHMMSS)"
echo " -l, --list 列出可用備份"
echo " -w, --website 恢復(fù)網(wǎng)站文件"
echo " -m, --mysql 恢復(fù)MySQL數(shù)據(jù)庫(kù)"
echo " -p, --postgresql 恢復(fù)PostgreSQL數(shù)據(jù)庫(kù)"
echo " -a, --all 恢復(fù)所有內(nèi)容"
}
list_backups() {
echo "可用的備份文件:"
ls -la ${BACKUP_DIR}/backup_*.tar.gz 2>/dev/null | while read file; do
local size=$(du -h "$file" | cut -f1)
local date=$(basename "$file" | sed 's/backup_\(.*\)\.tar\.gz/\1/')
echo " $date - $size - $file"
done
}
restore_website() {
local extract_dir="$1"
echo "恢復(fù)網(wǎng)站文件..."
if [ -f "${extract_dir}/website_files.tar.gz" ]; then
sudo tar xzf "${extract_dir}/website_files.tar.gz" -C /tmp/website_restore
echo "網(wǎng)站文件已提取到 /tmp/website_restore"
echo "請(qǐng)手動(dòng)將文件復(fù)制到目標(biāo)目錄"
else
echo "警告: 未找到網(wǎng)站文件備份"
fi
}
restore_mysql() {
local extract_dir="$1"
echo "恢復(fù)MySQL數(shù)據(jù)庫(kù)..."
for sql_file in "${extract_dir}"/mysql_*.sql.gz; do
if [ -f "$sql_file" ]; then
local db_name=$(basename "$sql_file" | sed 's/mysql_\(.*\)\.sql\.gz/\1/')
echo "恢復(fù)數(shù)據(jù)庫(kù): $db_name"
gunzip -c "$sql_file" | mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD"
if [ $? -eq 0 ]; then
echo "? 數(shù)據(jù)庫(kù)恢復(fù)成功: $db_name"
else
echo "? 數(shù)據(jù)庫(kù)恢復(fù)失敗: $db_name"
fi
fi
done
}
main() {
local backup_file=""
local restore_website=false
local restore_mysql=false
local restore_postgresql=false
while [[ $# -gt 0 ]]; do
case $1 in
-f|--file)
backup_file="$2"
shift 2
;;
-d|--date)
local date="$2"
backup_file="${BACKUP_DIR}/backup_${date}.tar.gz"
shift 2
;;
-l|--list)
list_backups
exit 0
;;
-w|--website)
restore_website=true
shift
;;
-m|--mysql)
restore_mysql=true
shift
;;
-p|--postgresql)
restore_postgresql=true
shift
;;
-a|--all)
restore_website=true
restore_mysql=true
restore_postgresql=true
shift
;;
*)
echo "未知選項(xiàng): $1"
show_usage
exit 1
;;
esac
done
if [ -z "$backup_file" ]; then
echo "錯(cuò)誤: 必須指定備份文件"
show_usage
exit 1
fi
if [ ! -f "$backup_file" ]; then
echo "錯(cuò)誤: 備份文件不存在: $backup_file"
exit 1
fi
# 創(chuàng)建臨時(shí)解壓目錄
local temp_dir=$(mktemp -d)
echo "解壓備份文件到: $temp_dir"
tar xzf "$backup_file" -C "$temp_dir"
# 執(zhí)行恢復(fù)操作
if [ "$restore_website" = true ]; then
restore_website "$temp_dir"
fi
if [ "$restore_mysql" = true ]; then
restore_mysql "$temp_dir"
fi
# 清理臨時(shí)文件
rm -rf "$temp_dir"
echo "恢復(fù)操作完成"
}
main "$@"
9. 使用說(shuō)明和測(cè)試
創(chuàng)建測(cè)試腳本驗(yàn)證整個(gè)系統(tǒng):
#!/bin/bash
# test_backup_system.sh
echo "開(kāi)始測(cè)試備份系統(tǒng)..."
# 測(cè)試配置文件
if [ -f "/opt/backups/config/backup.conf" ]; then
echo "? 配置文件存在"
else
echo "? 配置文件缺失"
exit 1
fi
# 測(cè)試主腳本
if [ -x "/opt/backups/scripts/website_backup.sh" ]; then
echo "? 主腳本可執(zhí)行"
else
echo "? 主腳本不可執(zhí)行"
exit 1
fi
# 測(cè)試數(shù)據(jù)庫(kù)連接
echo "測(cè)試數(shù)據(jù)庫(kù)連接..."
if mysql -h localhost -u backup_user -p'your_secure_password' -e "SELECT 1" > /dev/null 2>&1; then
echo "? MySQL連接正常"
else
echo "? MySQL連接失敗"
fi
# 執(zhí)行測(cè)試備份
echo "執(zhí)行測(cè)試備份..."
sudo -u backupuser /opt/backups/scripts/website_backup.sh
# 檢查備份結(jié)果
if [ $? -eq 0 ]; then
echo "? 備份測(cè)試成功"
else
echo "? 備份測(cè)試失敗"
exit 1
fi
echo "備份系統(tǒng)測(cè)試完成"
10. 總結(jié)
本教程提供了一個(gè)完整的企業(yè)級(jí)網(wǎng)站和數(shù)據(jù)庫(kù)備份解決方案,具有以下特點(diǎn):
- 全面性:支持網(wǎng)站文件、MySQL、PostgreSQL數(shù)據(jù)庫(kù)備份
- 可靠性:包含完整的錯(cuò)誤處理和日志記錄
- 自動(dòng)化:支持定時(shí)任務(wù)和自動(dòng)清理
- 多云支持:支持AWS S3、Google Cloud Storage、阿里云OSS
- 安全性:配置文件權(quán)限控制和敏感信息保護(hù)
- 可維護(hù)性:模塊化設(shè)計(jì)和詳細(xì)文檔
通過(guò)按照本教程逐步實(shí)施,您可以建立一個(gè)生產(chǎn)級(jí)別的自動(dòng)化備份系統(tǒng),確保網(wǎng)站數(shù)據(jù)的安全性和可恢復(fù)性。
到此這篇關(guān)于Shell腳本實(shí)現(xiàn)自動(dòng)備份網(wǎng)站和數(shù)據(jù)庫(kù)并上傳到云存儲(chǔ)的文章就介紹到這了,更多相關(guān)Shell腳本自動(dòng)備份網(wǎng)站和數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
shell腳本結(jié)合iptables防端口掃描的實(shí)現(xiàn)
這篇文章主要介紹了shell腳本結(jié)合iptables防端口掃描的實(shí)現(xiàn),中間使用了inotify-tools工具,需要的朋友可以參考下2014-05-05
shell腳本實(shí)現(xiàn)本地文件與服務(wù)器文件同步
這篇文章主要介紹了本地文件與服務(wù)器文件同步shell腳本的方法,然后在文章給大家補(bǔ)充介紹了shell腳本備份本地服務(wù)器的文件到遠(yuǎn)程服務(wù)器的實(shí)例代碼,需要的朋友可以參考下2017-11-11
CentOS7運(yùn)行.sh腳本提示syntax error: unexpected end of file的解決方法
這篇文章主要介紹了解決執(zhí)行腳本報(bào)syntax error: unexpected end of file或syntax error near unexpected token fi錯(cuò)誤的問(wèn)題,需要的朋友可以參考下2020-02-02
shell隨機(jī)定時(shí)修改密碼change_passwd.sh
這篇文章主要介紹了shell隨機(jī)定時(shí)修改密碼change_passwd.sh,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
shell腳本編程之if語(yǔ)句學(xué)習(xí)筆記
這篇文章主要介紹了shell腳本編程之if語(yǔ)句學(xué)習(xí)筆記,本文先是給出了程序代碼,然后詳細(xì)的分解了第句代碼的作用,需要的朋友可以參考下2014-09-09
關(guān)于Linux反空閑設(shè)置的兩種方法總結(jié)
下面小編就為大家?guī)?lái)一篇關(guān)于Linux反空閑設(shè)置的兩種方法總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03

