ubuntu服务器备份并上传到云盘

65次阅读
没有评论

共计 6613 个字符,预计需要花费 17 分钟才能阅读完成。

ubuntu服务器备份并上传到云盘

在服务器运维过程中,数据安全永远是第一位的。哪怕你技术再牛,也挡不住手一滑删了系统文件,或者硬盘突然罢工。所以,定期备份系统,是每个运维人员必须掌握的基本技能。

然后俺就让AI写了个脚本,它可以自动帮你做系统备份,还能把备份文件上传到阿里云盘,让你的数据更安全,也更方便恢复。

一、这个脚本能干啥?

这个脚本其实就是一个 .sh 文件,运行起来后可以帮你完成以下几件事:

  1. 增量备份系统文件(只备份变化的部分,节省空间)
  2. 打包压缩备份数据(生成 .tar.gz 文件)
  3. 上传到远程服务器(比如你家里的 NAS 或者另一台 VPS)
  4. 上传到阿里云盘(自动备份到云端)
  5. 自动清理旧备份(默认保留 7 天以内的备份)

二、脚本使用前的准备(建议使用root权限账号)

1. 安装必要工具

首先,你需要确保你的 Linux 系统已经安装了以下工具(rsync 用于高效同步文件,tar 用于打包文件,gzip 用于压缩文件,pv 用于实时查看管道中数据传输进度。):

sudo apt update
sudo apt install -y rsync tar gzip pv

如果你用的是 CentOS 或者 RedHat,换成:

sudo yum install -y rsync tar gzip pv

2. 创建备份目录

脚本默认会把备份文件存在 /sys-backup 目录下,你可以手动创建一下:

sudo mkdir -p /sys-backup/{rsyncback,backups,log}

三、安装和配置阿里云盘 CLI

这个脚本还支持把备份上传到阿里云盘,所以你得先装一个叫 aliyunpan 的命令行工具。

1. 下载安装

你可以从 GitHub 下载这个工具:

apt安装,适用于apt包管理器的系统,例如Ubuntu,国产deepin深度操作系统等。目前只支持amd64和arm64架构的机器,下面大概意思就是添加公钥,配置源,安装

sudo curl -fsSL http://file.tickstep.com/apt/pgp | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/tickstep-packages-archive-keyring.gpg > /dev/null && echo "deb [signed-by=/etc/apt/trusted.gpg.d/tickstep-packages-archive-keyring.gpg arch=amd64,arm64] http://file.tickstep.com/apt aliyunpan main" | sudo tee /etc/apt/sources.list.d/tickstep-aliyunpan.list > /dev/null && sudo apt-get update && sudo apt-get install -y aliyunpan

然后测试一下是否安装成功:

aliyunpan --version

2. 绑定阿里云账号

运行下面这个命令,会让你登录阿里云账号:

aliyunpan login

它会提示你打开一个链接,在浏览器中扫码登录,然后输入验证码。登录成功后,你的 Token 会被保存下来,以后上传文件就不用再登录了。

四、脚本怎么用

1. 创建脚本文件

#!/bin/bash
set -e

# ===== 配置部分 =====
BACKUP_ROOT="/sys-backup"
RSYNC_DIR="${BACKUP_ROOT}/rsyncback"
TAR_DIR="${BACKUP_ROOT}/backups"
LOG_DIR="${BACKUP_ROOT}/log"
LOG_FILE="${LOG_DIR}/backup.log"

# 远程服务器配置(可选)
REMOTE_SERVER=""                # "user@your.remote.server.com"
REMOTE_BACKUP_DIR="/backup"

# 阿里云盘配置
ALIYUN_REMOTE_DIR="/系统备份"

# 先创建必要目录(不重定向输出)
mkdir -p "${RSYNC_DIR}" "${TAR_DIR}" "${LOG_DIR}"

# 确保日志文件存在
touch "${LOG_FILE}"

# 获取服务器 IP
SERVER_IP=$(hostname -I | awk '{print $1}')
DATE=$(date +%Y%m%d-%H%M%S)

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "${LOG_FILE}"
    # 显示进度信息到终端
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# 安装进度条工具
install_pv() {
    if ! command -v pv &> /dev/null; then
        echo "正在安装进度条工具 pv..."
        if command -v apt &> /dev/null; then
            apt update && apt install -y pv
        elif command -v yum &> /dev/null; then
            yum install -y pv
        else
            echo "无法自动安装pv。请手动安装: apt install pv 或 yum install pv"
            return 1
        fi
    fi
    return 0
}

# rsync 增量备份
do_incremental_backup() {
    local INC_DIR="${BACKUP_ROOT}/.rsync-inc"
    log "开始增量备份..."

    # 清理旧临时目录
    if [ -d "${INC_DIR}" ]; then
        rm -rf "${INC_DIR}" &>> "${LOG_FILE}"
    fi
    mkdir -p "${INC_DIR}" &>> "${LOG_FILE}"

    # 定义排除路径
    local EXCLUDES=(
        "/proc" "/sys" "/lost+found" "/mnt" "/media" "/run" "/tmp"
        "/sys-backup" "/*.usr-is-merged" "/patch"
    )

    # 构建 rsync 排除参数
    local RSYNC_EXCLUDE_ARGS=()
    for path in "${EXCLUDES[@]}"; do
        RSYNC_EXCLUDE_ARGS+=( --exclude="$path" )
    done

    # 执行 rsync 增量备份
    if [ "$(ls -A "${RSYNC_DIR}")" ]; then
        log "执行增量备份到临时目录..."

        rsync -ah --info=progress2 --numeric-ids --delete \
            "${RSYNC_EXCLUDE_ARGS[@]}" \
            --link-dest="${RSYNC_DIR}" \
            / "${INC_DIR}/" 2>&1

        RSYNC_STATUS=${PIPESTATUS[0]}

    else
        log "首次备份,进行全量复制"

        rsync -ah --info=progress2 --numeric-ids --delete \
            "${RSYNC_EXCLUDE_ARGS[@]}" \
            / "${INC_DIR}/" 2>&1

        RSYNC_STATUS=${PIPESTATUS[0]}

    fi

    if [ $RSYNC_STATUS -eq 0 ]; then
        log "第一阶段备份完成"
    else
        log "rsync 失败,状态码: $RSYNC_STATUS"
        return 1
    fi

    # 合并到主备份目录
    log "合并到主备份目录..."

    rsync -ah --info=progress2 --delete "${INC_DIR}/" "${RSYNC_DIR}/" 2>&1 
    RSYNC2_STATUS=${PIPESTATUS[0]}

    if [ $RSYNC2_STATUS -eq 0 ]; then
        log "合并完成"
    else
        log "合并失败,状态码: $RSYNC2_STATUS"
        return 1
    fi

    rm -rf "${INC_DIR}" &>> "${LOG_FILE}"
    log "增量备份完成"
}


do_tar_backup() {

    local TAR_BASE="system_backup_${SERVER_IP}_${DATE}"
    local TAR_NAME="${TAR_DIR}/${TAR_BASE}.tar.gz"

    log "开始打包备份..."
    log "备份路径: ${RSYNC_DIR}"
    log "输出文件: ${TAR_NAME}"

    # 获取目录大小
    BACKUP_SIZE=$(du -sb "${RSYNC_DIR}" | awk '{print $1}')
    echo "目录大小:$(numfmt --to=iec $BACKUP_SIZE 2>/dev/null || echo "$BACKUP_SIZE bytes")"

    echo "正在打包,请等待进度条完成..."

    # 一步到位:tar + pv + gzip
    tar cf - -C "${RSYNC_DIR}" . | \
    pv -s "$BACKUP_SIZE" -N "打包中" --wait | \
    gzip > "${TAR_NAME}"

    TAR_STATUS=${PIPESTATUS[0]}
    if [ $TAR_STATUS -ne 0 ]; then
        log "打包失败,状态码: $TAR_STATUS"
        return 1
    fi

    # 检查文件是否存在
    if [[ -f "$TAR_NAME" ]]; then
        TAR_SIZE=$(du -h "$TAR_NAME" | awk '{print $1}')
        log "打包完成: ${TAR_NAME} (大小: $TAR_SIZE)"
    else
        log "错误:打包完成但文件不存在: $TAR_NAME"
        return 1
    fi
}

# 上传到远程服务器
do_upload_to_remote() {
    if [ -z "${REMOTE_SERVER}" ]; then
        log "未配置远程服务器,跳过上传"
        return 0
    fi

    local LATEST_TAR=$(ls -t "${TAR_DIR}/system_backup_${SERVER_IP}_*.tar.gz" 2>/dev/null | head -n1)
    if [ -z "${LATEST_TAR}" ]; then
        log "没有可上传的 tar 文件"
        return 1
    fi

    log "开始上传到远程服务器: ${REMOTE_SERVER}:${REMOTE_BACKUP_DIR}"

    if command -v pv &> /dev/null; then
        TAR_SIZE=$(du -sb "${LATEST_TAR}" | cut -f1)
        echo "文件大小:$(numfmt --to=iec $TAR_SIZE 2>/dev/null || echo "$TAR_SIZE bytes")"

        pv "${LATEST_TAR}" | ssh "${REMOTE_SERVER}" "cat > ${REMOTE_BACKUP_DIR}/$(basename "${LATEST_TAR}")"
        UPLOAD_STATUS=${PIPESTATUS[0]}
    else
        scp -v "${LATEST_TAR}" "${REMOTE_SERVER}:${REMOTE_BACKUP_DIR}/" 2>&1 | tee -a "${LOG_FILE}"
        UPLOAD_STATUS=$?
    fi

    if [ $UPLOAD_STATUS -eq 0 ]; then
        log "上传完成"
    else
        log "上传失败,状态码: $UPLOAD_STATUS"
        return 1
    fi
    return 0
}

# 上传到阿里云盘
do_upload_to_aliyunpan() {
    echo "${TAR_DIR}"
    ls -l ${TAR_DIR}/system_backup_${SERVER_IP}_*.tar.gz
    local LATEST_TAR=$(ls -t ${TAR_DIR}/system_backup_${SERVER_IP}_*.tar.gz 2>/dev/null | head -n1)
    if [ -z "${LATEST_TAR}" ]; then
        log "没有可上传的 tar 文件"
        return 1
    fi

    # 检查aliyunpan命令是否存在
    if ! command -v aliyunpan &> /dev/null; then
        log "阿里云盘客户端未安装,跳过上传"
        return 1
    fi

    log "开始上传到阿里云盘: ${LATEST_TAR}"
    aliyunpan upload "${LATEST_TAR}" "${ALIYUN_REMOTE_DIR}"
    log "阿里云盘上传任务已启动"
    return 0
}

# 清理旧备份
do_cleanup() {
    log "清理 7 天前的 tar 文件"
    find "${TAR_DIR}" -type f -name "system_backup_${SERVER_IP}_*.tgz" -mtime +7 -exec rm -f {} \; &>> "${LOG_FILE}"
    return 0
}

# ===== 主逻辑 =====

if [ $# -ne 1 ]; then
    echo "用法: $0 [incr|tar|upload|clean|all]" | tee -a "${LOG_FILE}"
    exit 1
fi

case "$1" in
    incr)
        do_incremental_backup
        ;;
    tar)
        do_tar_backup
        ;;
    upload)
        do_upload_to_remote
        do_upload_to_aliyunpan
        ;;
    clean)
        do_cleanup
        ;;
    all)
        do_incremental_backup
        do_tar_backup
        do_upload_to_remote
        do_upload_to_aliyunpan
        do_cleanup
        ;;
    *)
        echo "无效模式: $1" | tee -a "${LOG_FILE}"
        echo "用法: $0 [incr|tar|upload|clean|all]" | tee -a "${LOG_FILE}"
        exit 1
        ;;
esac

log "任务完成: $1"

你可以把脚本保存成一个文件,比如叫 backup.sh,然后给它执行权限:

chmod +x backup.sh

2. 修改配置

打开脚本,找到开头的配置部分,根据你的实际情况修改:

REMOTE_SERVER="user@your.remote.server.com"   # 远程服务器地址(可选)
REMOTE_BACKUP_DIR="/backup"                  # 远程服务器备份路径
ALIYUN_REMOTE_DIR="/系统备份"                # 阿里云盘上的备份目录

如果你不想上传到远程服务器,就把 REMOTE_SERVER 设置为空。

五、运行脚本 ps:阿里云盘有时候上传很慢,具体我也不知道什么情况

脚本支持几种不同的运行模式:

./backup.sh incr      # 只做增量备份
./backup.sh tar       # 只打包备份
./backup.sh upload    # 只上传备份
./backup.sh clean     # 清理旧备份
./backup.sh all       # 执行全部操作:增量备份 + 打包 + 上传 + 清理

建议你第一次运行用 all 模式,这样会完整跑一遍流程,看看有没有报错。

六、设置定时备份 ps:自动执行,也可以手动执行,根据你的情况来

为了避免手动执行,我们可以用 Linux 的定时任务工具 cron 来每天自动备份,-不建议

运行下面命令打开定时任务编辑器:

crontab -e

添加一行内容(比如每天凌晨 2 点执行):

0 2 * * * /path/to/backup.sh all >> /sys-backup/log/backup_cron.log 2>&1

这样,每天早上 2 点系统就会自动执行备份,把日志写进 /sys-backup/log/backup_cron.log

七、注意事项

  • 权限问题:确保脚本能读取系统文件,尤其是 / 目录下的内容。
  • 排除目录:脚本默认排除了 /proc/sys/tmp 这些目录,避免备份无用数据。
  • 阿里云盘路径:上传前请确保阿里云盘上有 /系统备份 这个目录,否则会上传失败。
  • 日志查看:如果备份失败,可以查看 /sys-backup/log/backup.log,里面有详细的错误信息。
  • 磁盘空间:增量备份虽然节省空间,但也要注意 /sys-backup 所在分区的容量。

八、结语

这个脚本虽然看起来有点复杂,但其实只要配置一次,就能长期帮你自动备份系统,还能上传到阿里云盘,非常实用。对于个人服务器、小公司运维来说,是一个性价比很高的解决方案。


如果有更好的方式方法,欢迎大佬们交流指导

正文完
 0
grbox
版权声明:本站原创文章,由 grbox 于2025-07-21发表,共计6613字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码