diff --git a/z.ai/ftp_backup.sh b/z.ai/ftp_backup.sh deleted file mode 100644 index c5b618b..0000000 --- a/z.ai/ftp_backup.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/bin/bash - -# ============================================================================== -# 脚本名称: ftp_backup.sh -# 功能描述: 将指定的一个或多个目录打包压缩后,自动上传到FTP服务器。 -# 调用方式: ./ftp_backup.sh 目录1 [目录2] [目录3] ... -# 作者: AI Assistant -# 版本: 1.1 -# ============================================================================== - -# --- 配置区 (请在此处修改您的FTP服务器信息) --- - -# FTP服务器信息 -FTP_HOST="your_ftp_server_ip" # FTP服务器IP地址或域名 -FTP_PORT="21" # FTP服务器端口 (默认为21) -FTP_USER="your_username" # FTP登录用户名 -FTP_PASS="your_password" # FTP登录密码 - -# 上传到FTP服务器的哪个目录 (如果不存在,请确保FTP账户有创建权限,或手动创建) -FTP_REMOTE_DIR="/backup" - -# 本地临时目录,用于存放生成的压缩包 (通常使用/tmp) -TEMP_BACKUP_DIR="/tmp" - -# --- 配置区结束 --- - - -# --- 脚本主逻辑 (通常无需修改以下内容) --- - -# 开启严格模式:遇到错误立即退出,使用未定义变量时报错,管道中任一命令失败则整个管道失败 -set -euo pipefail - -# 定义一个清理函数,用于在脚本退出时删除临时文件 -cleanup() { - if [[ -n "${ARCHIVE_NAME:-}" && -f "${TEMP_BACKUP_DIR}/${ARCHIVE_NAME}" ]]; then - echo "清理临时文件: ${TEMP_BACKUP_DIR}/${ARCHIVE_NAME}" - rm -f "${TEMP_BACKUP_DIR}/${ARCHIVE_NAME}" - fi -} - -# 无论脚本如何退出(成功、失败、被中断),都会执行cleanup函数 -trap cleanup EXIT - -# 显示使用方法 -usage() { - echo "用法: $0 目录1 [目录2] [目录3] ..." - echo "示例: $0 /var/www/html /etc/nginx /home/user/documents" - exit 1 -} - -# 检查并安装ftp客户端 -check_dependencies() { - echo "正在检查 ftp 客户端是否已安装..." - if ! command -v ftp &> /dev/null; then - echo "ftp 客户端未找到,正在尝试自动安装..." - # 检测操作系统类型 - if [[ -f /etc/debian_version ]]; then - # Debian/Ubuntu 系统 - echo "检测到 Debian/Ubuntu 系统,使用 apt-get 安装..." - sudo apt-get update - sudo apt-get install -y ftp - elif [[ -f /etc/redhat-release ]]; then - # CentOS/RHEL/Fedora 系统 - echo "检测到 RedHat/CentOS 系统,使用 yum 安装..." - sudo yum install -y ftp - else - echo "错误: 无法识别您的Linux发行版,请手动安装 ftp 客户端。" - exit 1 - fi - - # 再次检查是否安装成功 - if ! command -v ftp &> /dev/null; then - echo "错误: ftp 客户端安装失败!" - exit 1 - fi - echo "ftp 客户端安装成功。" - else - echo "ftp 客户端已安装。" - fi -} - -# 创建压缩包 -create_archive() { - local dirs_to_backup=("$@") - # 生成唯一的压缩包名:主机名_时间戳.tar.gz - ARCHIVE_NAME="backup_$(hostname)_$(date +%Y%m%d_%H%M%S).tar.gz" - local full_archive_path="${TEMP_BACKUP_DIR}/${ARCHIVE_NAME}" - - echo "正在创建压缩包: ${full_archive_path}" - echo "包含的目录: ${dirs_to_backup[*]}" - - # 使用 tar 命令创建 .tar.gz 压缩包 - # -c: 创建, -z: gzip压缩, -f: 指定文件名, -p: 保留权限 - tar -czpf "${full_archive_path}" "${dirs_to_backup[@]}" - - echo "压缩包创建成功!" -} - -# 上传到FTP服务器 -upload_to_ftp() { - local local_file="${TEMP_BACKUP_DIR}/${1}" - echo "正在上传 ${local_file} 到 FTP 服务器 ${FTP_HOST}:${FTP_PORT}${FTP_REMOTE_DIR}" - - # 使用 ftp 的 -inv 选项进行非交互式上传 - # -i: 关闭交互式提示 - # -n: 禁止自动登录 - # -v: 显示详细输出 - ftp -inv << EOF -open ${FTP_HOST} ${FTP_PORT} -user ${FTP_USER} ${FTP_PASS} -binary -mkdir ${FTP_REMOTE_DIR} -cd ${FTP_REMOTE_DIR} -put ${local_file} ${1} -bye -EOF - - echo "文件上传成功!" -} - - -# ============================================================================== -# 主程序入口 -# ============================================================================== - -# 1. 检查是否提供了目录参数 -if [ "$#" -eq 0 ]; then - usage -fi - -# 2. 验证所有提供的目录是否存在 -echo "正在验证输入的目录..." -for dir in "$@"; do - if [ ! -d "$dir" ]; then - echo "错误: 目录 '$dir' 不存在!" - exit 1 - fi -done -echo "所有目录验证通过。" - -# 3. 检查并安装依赖 -check_dependencies - -# 4. 创建压缩包 -create_archive "$@" - -# 5. 上传压缩包 -upload_to_ftp "${ARCHIVE_NAME}" - -# 6. 脚本执行完毕 -echo "=========================================" -echo "备份任务全部完成!" -echo "备份文件: ${ARCHIVE_NAME}" -echo "=========================================" - -exit 0 \ No newline at end of file diff --git a/z.ai/shell/ftp_backup.sh b/z.ai/shell/ftp_backup.sh new file mode 100644 index 0000000..773df06 --- /dev/null +++ b/z.ai/shell/ftp_backup.sh @@ -0,0 +1,175 @@ +#!/bin/bash + +# ============================================================================== +# 脚本名称: ftp_backup.sh +# 功能描述: 将指定的一个或多个目录通过数据流打包并直接上传到FTP服务器。 +# 无需生成临时文件,高效且节省磁盘空间。 +# 调用方式: +# 1. 交互式输入密码 (推荐, 更安全): +# ./ftp_backup.sh 目录1 [目录2] ... +# 2. 通过 -p 参数指定密码 (不推荐, 有安全风险): +# ./ftp_backup.sh -p '你的密码' 目录1 [目录2] ... +# 作者: AI Assistant +# 版本: 2.0 +# ============================================================================== + +# --- 配置区 (请在此处修改您的FTP服务器信息) --- + +# FTP服务器信息 +FTP_HOST="your_ftp_server_ip" # FTP服务器IP地址或域名 +FTP_PORT="21" # FTP服务器端口 (默认为21) +FTP_USER="your_username" # FTP登录用户名 +# 密码将在运行时通过交互式输入或 -p 参数提供 + +# 上传到FTP服务器的哪个目录 (如果不存在,请确保FTP账户有创建权限) +FTP_REMOTE_DIR="/backup" + +# --- 配置区结束 --- + + +# --- 脚本主逻辑 (通常无需修改以下内容) --- + +# 开启严格模式 +set -euo pipefail + +# 用于存储密码的变量 +FTP_PASS="" + +# 显示使用方法 +usage() { + echo "用法:" + echo " $0 目录1 [目录2] ... # 交互式输入密码 (推荐)" + echo " $0 -p '密码' 目录1 [目录2] ... # 通过参数提供密码 (不安全)" + echo "" + echo "示例:" + echo " $0 /var/www/html /etc/nginx" + echo " $0 -p 'MyP@ssw0rd!' /home/user" + exit 1 +} + +# 检查并安装依赖包 (兼容 Alpine, Debian/Ubuntu, RHEL/CentOS/Fedora) +install_package_if_missing() { + local package_name="$1" + if ! command -v "${package_name}" &> /dev/null; then + echo "依赖 '${package_name}' 未找到,正在尝试自动安装..." + # 检测包管理器并安装 + if command -v apk &> /dev/null; then + echo "检测到 Alpine 系统,使用 apk 安装..." + sudo apk add "${package_name}" + elif command -v apt-get &> /dev/null; then + echo "检测到 Debian/Ubuntu 系统,使用 apt-get 安装..." + sudo apt-get update && sudo apt-get install -y "${package_name}" + elif command -v dnf &> /dev/null; then + echo "检测到使用 dnf 的系统 (如 Fedora/RHEL 8+),使用 dnf 安装..." + sudo dnf install -y "${package_name}" + elif command -v yum &> /dev/null; then + echo "检测到使用 yum 的系统 (如 CentOS 7),使用 yum 安装..." + sudo yum install -y "${package_name}" + else + echo "错误: 无法识别您的包管理器,请手动安装 '${package_name}'。" + exit 1 + fi + + # 再次检查 + if ! command -v "${package_name}" &> /dev/null; then + echo "错误: '${package_name}' 安装失败!" + exit 1 + fi + echo "'${package_name}' 安装成功。" + else + echo "依赖 '${package_name}' 已满足。" + fi +} + +# 流式打包并上传 +stream_and_upload() { + local dirs_to_backup=("$@") + # 生成唯一的压缩包名 + local archive_name="backup_$(hostname)_$(date +%Y%m%d_%H%M%S).tar.gz" + local ftp_url="ftp://${FTP_HOST}:${FTP_PORT}${FTP_REMOTE_DIR}/${archive_name}" + + echo "=========================================" + echo "准备开始流式备份和上传..." + echo "目标FTP: ${FTP_HOST}:${FTP_PORT}" + echo "远程目录: ${FTP_REMOTE_DIR}" + echo "备份内容: ${dirs_to_backup[*]}" + echo "远程文件名: ${archive_name}" + echo "=========================================" + + # 使用 tar 和 curl 管道进行流式处理 + # tar -czf - : - 表示输出到标准输出 + # curl -T - : -T - 表示从标准输入读取文件内容上传 + # -u : 提供用户名和密码 + # --ftp-create-dirs : 自动创建远程目录 (如果需要) + # --ftp-pasv : 使用被动模式 (更兼容防火墙) + # 我们使用 PIPESTATUS 来检查管道中任何一个命令是否失败 + tar -czpf - "${dirs_to_backup[@]}" | curl -T - -u "${FTP_USER}:${FTP_PASS}" --ftp-create-dirs --ftp-pasv "${ftp_url}" + + # 检查管道命令的退出状态 + if [[ ${PIPESTATUS[0]} -ne 0 || ${PIPESTATUS[1]} -ne 0 ]]; then + echo "错误: 打包或上传过程中失败!" + echo "tar 退出码: ${PIPESTATUS[0]}, curl 退出码: ${PIPESTATUS[1]}" + exit 1 + fi + + echo "=========================================" + echo "备份任务全部完成!" + echo "文件已成功上传为: ${archive_name}" + echo "=========================================" +} + + +# ============================================================================== +# 主程序入口 +# ============================================================================== + +# 1. 解析命令行参数 +while getopts ":p:" opt; do + case ${opt} in + p ) + FTP_PASS="${OPTARG}" + ;; + \? ) + echo "无效的选项: -$OPTARG" 1>&2 + usage + ;; + : ) + echo "选项 -$OPTARG 需要一个参数." 1>&2 + usage + ;; + esac +done +shift $((OPTIND -1)) + +# 2. 检查是否提供了目录参数 +if [ "$#" -eq 0 ]; then + usage +fi + +# 3. 如果没有通过 -p 提供密码,则交互式输入 +if [[ -z "${FTP_PASS}" ]]; then + echo "请输入FTP密码:" + # -s: 静默输入,不回显到屏幕 + # -r: 允许输入反斜杠,防止特殊字符被转义 + read -sr FTP_PASS + echo "" # 换行 +fi + +# 4. 验证所有提供的目录是否存在 +echo "正在验证输入的目录..." +for dir in "$@"; do + if [ ! -d "$dir" ]; then + echo "错误: 目录 '$dir' 不存在!" + exit 1 + fi +done +echo "所有目录验证通过。" + +# 5. 检查并安装依赖 (curl 和 tar) +install_package_if_missing "curl" +install_package_if_missing "tar" + +# 6. 执行流式打包和上传 +stream_and_upload "$@" + +exit 0 \ No newline at end of file