Skip to content
sh
#!/bin/bash

#   chmod +x data.sh ; bash ./data.sh backup
mount_point=/mnt/nfs
remote_dir=/mnt/nfs/System/配置/_服务器/文件/Server_2
last_archive=$remote_dir/all_last.gz

tmp_dir=/tmp/my_Backup_cache
file_list=$tmp_dir/list
# tmp_path=$tmp_dir/backup.gz
custom_data=/tmp/my_Backup
ufw_rules=$custom_data/ufw_rules.txt

mkdir -p $tmp_dir $custom_data

keep_count=3  # 保留的最新文件数量
pattern=".gz" # 文件名包含的特定字符串

Owner_Group=3000:950

# 备份清单
echo "/app" >$file_list
echo "/root/.ssh" >>$file_list
echo "/etc/ufw" >>$file_list
echo "/opt/1panel" >>$file_list
echo "/etc/TLS" >>$file_list
echo "/etc/hysteria" >>$file_list
echo "/etc/x-ui" >>$file_list

# 检查文件系统是否已挂载
if ! mountpoint -q "$mount_point"; then
    echo "文件系统未挂载,正在重新挂载..."
    mount -a
    if [ $? -ne 0 ]; then
        echo "挂载失败,请检查挂载点和文件系统。"
        exit 1
    fi
else
    echo "文件系统已挂载。"
fi

current_filesystems=$(df -h | awk '{print $6}') # 记录当前的文件系统。使用 df -h 获取当前的文件系统,并使用 awk 提取第六列(挂载点)。

function talking_start() {
    echo ------------------------------备份数据------------------------------
    echo -e "\033[46m\033[30m╭------------------------------------------------------------╮\033[0m"
    echo -e "\033[46m\033[30m|    今天要去什么样的冒险呢?爱丽丝准备好一起踏上旅程了。    |\033[0m"
    echo -e "\033[46m\033[30m╰------------------------------------------------------------╯\033[0m" # 浅蓝
}
function talking_backup() {
    echo -e "\033[43m\033[30m╭------------------------------------------╮\033[0m"
    echo -e "\033[43m\033[30m|    在这光芒中注入意志…贯穿!平衡崩溃!   |\033[0m"
    echo -e "\033[43m\033[30m╰------------------------------------------╯\033[0m" # 橙色
}
function talking_rollback() {
    echo ------------------------------回滚数据------------------------------
    echo -e "\033[46m\033[30m╭--------------------------------------------------------------------╮\033[0m"
    echo -e "\033[46m\033[30m|    游戏、猫咪、好友们… 还有这一刻。这个世界上有很多美好的东西。    |\033[0m"
    echo -e "\033[46m\033[30m╰--------------------------------------------------------------------╯\033[0m" # 浅蓝
}
function talking_recovered() {
    echo -e "\033[46m\033[30m╭----------------------╮\033[0m"
    echo -e "\033[46m\033[30m|    老师,请指示。    |\033[0m"
    echo -e "\033[46m\033[30m╰----------------------╯\033[0m" # 浅蓝
}

function clear_up() {

    # 删除较旧的文件,只保留几个,文件名包含特定字符
    # ls -tp "$directory" | grep -v '/$' | grep "$pattern" | tail -n +$((keep_count+1)) | xargs -I {} rm -- "$directory/{}" # 时间精度只有分钟
    find "$remote_dir" -maxdepth 1 -type f -name "*$pattern*" -printf '%T@ %p\n' | sort -n | awk '{print $2}' | head -n -$keep_count | xargs -I {} rm -- {}

    # 修正权限
    chown $Owner_Group $remote_dir/*

    sleep 1                                                                                               # 等待几秒钟以确保文件系统更新
    new_filesystems=$(df -h | awk '{print $6}')                                                           # 检查新的文件系统
    added_filesystems=$(comm -13 <(echo "$current_filesystems" | sort) <(echo "$new_filesystems" | sort)) # 找出新增的文件系统。比较两个已排序的文件列表,输出仅在第二个文件中存在的行(即新增的文件系统)。
    for fs in $added_filesystems; do                                                                      # 删除新增的文件系统
        umount $fs
    done
    # echo "新增的文件系统已删除。"

    rm -rf $tmp_dir $custom_data

}

function maintenance_status() {
    1pctl stop | cat # 停止 1Panel

    running_containers=$(docker ps -q)
    docker stop $running_containers # 停止所有容器
}

function working_state() {
    echo ------------------------------恢复运行------------------------------
    clear_up

    1pctl restart | cat
    docker restart Portainer qBittorrentEE
    docker start $running_containers

    talking_recovered
}

function ufw_reload() {
    # Check if ufw is active
    ufw_status=$(ufw status | grep -oE 'Status: (active|inactive)' | awk '{print $2}')

    # Restore ufw status
    if [ "$ufw_status" == "inactive" ]; then
        echo "UFW 被禁用"
    else
        # Restart ufw
        sudo ufw disable
        yes | sudo ufw enable

        echo "UFW 已重启"
    fi

    echo "ufw has been restarted and its previous state has been restored."

}

# # 定义函数
# ufw_manage() {
#     # 保存当前的 UFW 状态
#     ufw_status=$(ufw status | grep -oE 'Status: (active|inactive)' | awk '{print $2}')

#     # 回滚 UFW 规则
#     yes | sudo ufw enable

#     # 在此处执行传入的命令
#     "$@"

#     # 恢复先前的 UFW 状态
#     if [ "$ufw_status" == "inactive" ]; then
#         sudo ufw disable
#         echo "UFW has been disabled."
#     else
#         echo "UFW remains enabled."
#     fi
# }

# # 示例调用
# # func echo "Hello, World!"
# # func bash ./test.sh

# function ufw_backup() {

#     ufw_manage sudo ufw status numbered >$ufw_rules

#     echo "Press any key to continue..."
#     read -n 1  # 等待用户按下任意键

#     echo $custom_data >>$file_list

# }
# function ufw_rollback() {

#     # 备份当前规则
#     local src_dir="/etc/ufw"
#     local backup_dir="$src_dir/backup"
#     find "$src_dir" -maxdepth 1 -type f -name "*rule*" -exec cp {} "$backup_dir" \; # 复制文件名包含 "rule" 的文件到备份目录

#     yes | ufw reset

#     # 删除ufw创建的备份文件。
#     for file in "$src_dir"/*; do # 删除文件名后缀类似 "20240806_153054" 的文件
#         if [[ "$file" =~ \.[0-9]{8}_[0-9]{6}$ ]]; then
#             rm "$file"
#         fi
#     done

#     ufw_manage yes | sudo ufw status numbered <$ufw_rules

#     # # 保存当前的 UFW 状态
#     # ufw_status=$(ufw status | grep -oE 'Status: (active|inactive)' | awk '{print $2}')

#     # # 回滚 UFW 规则
#     # yes | sudo ufw enable
#     # yes | sudo ufw status numbered <$ufw_rules

#     # # 恢复先前的 UFW 状态
#     # if [ "$ufw_status" == "inactive" ]; then
#     #     sudo ufw disable
#     #     echo "UFW has been disabled."
#     # else
#     #     echo "UFW remains enabled."
#     # fi
# }

function backup_app_data() {

    talking_start

    now=$(date +"%Y-%m-%d_%H-%M-%S")
    new_name=all_${now}.gz
    remote_path="$remote_dir/$new_name"
    echo $remote_path
    maintenance_status

    # 备份
    tar -czvf $remote_path -T $file_list
    talking_backup

    cd $remote_dir
    ln -sf ./$new_name ./all_last.gz #创建快捷方式
    # ln -sf $remote_path $last_archive #创建快捷方式

    working_state

}

function rollback_app_data() {
    talking_rollback
    maintenance_status

    # 恢复
    mv /app /app.old
    # cp -L $last_archive $tmp_path # 复制软链接指向的文件

    tar -xzvf $last_archive -C / # 解压到原位
    ufw_reload

    working_state
}

case $1 in
backup) backup_app_data ;;
rollback) rollback_app_data ;;
*) echo "无效的命令。可用命令:backup, rollback" ;;
esac