Files

292 lines
7.2 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# FTP备份脚本
# 用法: ./ftp_backup.sh -p密码 目录1 目录2 目录3 文件1
set -e # 遇到错误立即退出
# 配置信息(请根据实际情况修改)
FTP_SERVER="ftp.example.com"
FTP_PORT="21"
FTP_USER="username"
BACKUP_PREFIX="backup"
REMOTE_PATH="/backups"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
}
warn() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] 警告: $1${NC}"
}
error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] 错误: $1${NC}" >&2
exit 1
}
# 显示用法信息
usage() {
echo "用法: $0 -p密码 目录1 目录2 目录3 文件1"
echo "选项:"
echo " -p密码 FTP密码(包含特殊字符时请直接跟在-p后面)"
echo "示例: $0 -pMy@Complex#Password123 /home/user /etc /var/log /important/file.txt"
exit 1
}
# 检测系统类型并安装FTP客户端
install_ftp_client() {
local ftp_client=""
# 检测系统类型
if command -v apt-get >/dev/null 2>&1; then
log "检测到 Debian/Ubuntu 系统"
ftp_client="ftp"
apt-get update && apt-get install -y $ftp_client
elif command -v yum >/dev/null 2>&1; then
log "检测到 RHEL/CentOS 系统"
ftp_client="ftp"
yum install -y $ftp_client
elif command -v dnf >/dev/null 2>&1; then
log "检测到 Fedora/RHEL 8+ 系统"
ftp_client="ftp"
dnf install -y $ftp_client
elif command -v apk >/dev/null 2>&1; then
log "检测到 Alpine 系统"
ftp_client="lftp"
apk add --no-cache $ftp_client
elif command -v zypper >/dev/null 2>&1; then
log "检测到 openSUSE 系统"
ftp_client="ftp"
zypper install -y $ftp_client
else
error "无法检测系统类型或不受支持的系统"
fi
# 验证安装是否成功
if command -v ftp >/dev/null 2>&1 || command -v lftp >/dev/null 2>&1; then
log "FTP客户端安装/验证成功"
else
error "FTP客户端安装失败"
fi
}
# 检查FTP客户端是否已安装
check_ftp_client() {
if command -v ftp >/dev/null 2>&1; then
FTP_CMD="ftp"
log "找到 ftp 命令"
elif command -v lftp >/dev/null 2>&1; then
FTP_CMD="lftp"
log "找到 lftp 命令"
else
warn "未找到FTP客户端,尝试安装..."
install_ftp_client
# 重新检查
if command -v ftp >/dev/null 2>&1; then
FTP_CMD="ftp"
elif command -v lftp >/dev/null 2>&1; then
FTP_CMD="lftp"
else
error "FTP客户端安装后仍然不可用"
fi
fi
}
# 解析命令行参数
parse_arguments() {
local password_provided=0
if [ $# -eq 0 ]; then
usage
fi
# 解析-p参数
while getopts "p:" opt; do
case $opt in
p)
FTP_PASS="$OPTARG"
password_provided=1
;;
\?)
usage
;;
esac
done
shift $((OPTIND -1))
# 检查密码是否提供
if [ $password_provided -eq 0 ]; then
error "必须通过 -p参数 提供FTP密码"
fi
# 检查是否有备份目标
if [ $# -eq 0 ]; then
error "必须指定至少一个目录或文件进行备份"
fi
# 存储要备份的路径
BACKUP_PATHS=("$@")
log "密码参数已接收"
log "备份目标: ${BACKUP_PATHS[*]}"
}
# 验证备份路径是否存在
validate_paths() {
local invalid_paths=()
for path in "${BACKUP_PATHS[@]}"; do
if [ ! -e "$path" ]; then
warn "路径不存在: $path"
invalid_paths+=("$path")
fi
done
if [ ${#invalid_paths[@]} -eq ${#BACKUP_PATHS[@]} ]; then
error "所有指定的备份路径都不存在"
elif [ ${#invalid_paths[@]} -gt 0 ]; then
warn "以下路径将被忽略: ${invalid_paths[*]}"
# 移除无效路径
local valid_paths=()
for path in "${BACKUP_PATHS[@]}"; do
if [ -e "$path" ]; then
valid_paths+=("$path")
fi
done
BACKUP_PATHS=("${valid_paths[@]}")
fi
}
# 创建备份文件
create_backup() {
local timestamp=$(date +'%Y%m%d_%H%M%S')
BACKUP_FILE="${BACKUP_PREFIX}_${timestamp}.tar.gz"
log "开始创建备份文件: $BACKUP_FILE"
# 创建临时目录
local temp_dir=$(mktemp -d)
trap 'rm -rf "$temp_dir"' EXIT
# 复制要备份的文件和目录到临时位置,保持相对路径结构
for path in "${BACKUP_PATHS[@]}"; do
if [ -e "$path" ]; then
local parent_dir=$(dirname "$path")
local base_name=$(basename "$path")
if [ "$parent_dir" = "/" ]; then
# 处理根目录下的文件/目录
cp -r "$path" "$temp_dir/root_$base_name"
else
# 创建父目录结构并复制
mkdir -p "$temp_dir/$parent_dir"
cp -r "$path" "$temp_dir/$parent_dir/"
fi
fi
done
# 创建tar.gz压缩包
if tar -czf "$BACKUP_FILE" -C "$temp_dir" . 2>/dev/null; then
log "备份文件创建成功: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))"
else
error "创建备份文件失败"
fi
}
# 使用ftp命令上传
upload_with_ftp() {
log "使用ftp上传文件..."
# 创建ftp命令脚本
local ftp_script=$(mktemp)
cat > "$ftp_script" << EOF
open $FTP_SERVER $FTP_PORT
user $FTP_USER $FTP_PASS
binary
mkdir $REMOTE_PATH
cd $REMOTE_PATH
put $BACKUP_FILE
quit
EOF
if ftp -n < "$ftp_script" > /tmp/ftp_upload.log 2>&1; then
log "FTP上传成功"
rm -f "$ftp_script" "/tmp/ftp_upload.log"
return 0
else
error "FTP上传失败,查看 /tmp/ftp_upload.log 获取详细信息"
fi
}
# 使用lftp命令上传(Alpine Linux
upload_with_lftp() {
log "使用lftp上传文件..."
if lftp -e "set ftp:ssl-allow no; open $FTP_SERVER; user $FTP_USER '$FTP_PASS'; mkdir -p $REMOTE_PATH; cd $REMOTE_PATH; put $BACKUP_FILE; quit" > /tmp/lftp_upload.log 2>&1; then
log "LFTP上传成功"
rm -f "/tmp/lftp_upload.log"
return 0
else
error "LFTP上传失败,查看 /tmp/lftp_upload.log 获取详细信息"
fi
}
# 上传备份文件
upload_backup() {
log "开始上传备份文件到 $FTP_SERVER:$REMOTE_PATH"
case $FTP_CMD in
"ftp")
upload_with_ftp
;;
"lftp")
upload_with_lftp
;;
*)
error "不支持的FTP命令: $FTP_CMD"
;;
esac
}
# 清理临时文件
cleanup() {
if [ -f "$BACKUP_FILE" ]; then
rm -f "$BACKUP_FILE"
log "已清理本地备份文件: $BACKUP_FILE"
fi
}
# 主函数
main() {
log "FTP备份脚本开始执行"
# 解析参数
parse_arguments "$@"
# 验证路径
validate_paths
# 检查FTP客户端
check_ftp_client
# 创建备份
create_backup
# 上传备份
upload_backup
# 清理
cleanup
log "FTP备份完成!"
}
# 脚本入口点
main "$@"