如何在Bash中筛选各服务器组下最新的.vbk格式全量备份文件
筛选每个服务器组的最新.vbk备份文件
针对你的需求,这里提供两种可靠的实现方法,分别基于文件名中的时间戳和系统文件修改时间来筛选最新文件,同时给出脚本的完整优化建议:
方法一:基于文件名中的时间戳筛选
你的文件名格式包含可排序的时间戳Dyyyy-mm-ddThhmmss,可以直接提取该部分进行比较,确保准确对应备份生成时间,不受系统文件时间变动影响。
实现代码
#!/bin/bash # 初始化关联数组,存储每个服务器组的最新文件 declare -A latest_files # 遍历所有.vbk文件 for file in *.vbk; do # 跳过非文件(比如目录或空匹配) [[ ! -f "$file" ]] && continue # 提取服务器标识(从开头到"D"之前的部分,即"服务器名 - IP") server_id=$(echo "$file" | sed -n 's/\(.*D\).*/\1/p' | sed 's/D$//') # 提取时间戳部分(D后面到_之前的部分) timestamp=$(echo "$file" | sed -n 's/.*D\([0-9-T]*\)_.*/\1/p') # 对比当前服务器组已记录的最新时间戳,更新为更大的那个 if [[ -z "${latest_files[$server_id]}" ]]; then latest_files[$server_id]="$file" else # 提取已记录文件的时间戳 existing_timestamp=$(echo "${latest_files[$server_id]}" | sed -n 's/.*D\([0-9-T]*\)_.*/\1/p') # 比较时间戳(因为格式是yyyy-mm-ddThhmmss,字符串比较即可) if [[ "$timestamp" > "$existing_timestamp" ]]; then latest_files[$server_id]="$file" fi fi done # 输出每个服务器组的最新文件 echo "筛选出的最新全量备份文件:" for server in "${!latest_files[@]}"; do echo "- $server: ${latest_files[$server]}" done
代码说明
- 用关联数组
latest_files来分组存储每个服务器的最新文件,键是服务器的“名称-IP”标识 - 通过
sed命令精准提取服务器标识和时间戳,避免文件名中其他字符干扰 - 利用时间戳的字符串排序特性(
yyyy-mm-ddThhmmss格式天然支持字典序比较),直接判断哪个时间更新
方法二:基于系统文件修改时间筛选
如果备份文件的系统修改时间和实际生成时间一致,这种方法更简洁,依赖系统文件属性来排序。
实现代码
#!/bin/bash # 按修改时间倒序列出所有.vbk文件,然后按服务器分组取第一个 ls -lt -- *.vbk 2>/dev/null | awk ' BEGIN { prev_server = "" } { # 提取服务器标识(从开头到"D"之前的部分) match($NF, /(.*D)/, server_match) server_id = substr(server_match[1], 1, length(server_match[1])-1) # 只保留每个服务器组的第一个(最新的)文件 if (server_id != prev_server) { print $NF prev_server = server_id } } '
代码说明
ls -lt按修改时间从新到旧列出文件awk遍历列表,提取每个文件的服务器标识,只输出每个组的第一个(最新的)文件2>/dev/null用来屏蔽当目录中没有.vbk文件时的错误提示
额外实用建议(针对你的完整需求)
定时任务设置:要实现每月第一个周一执行,在crontab中添加以下规则(编辑crontab用
crontab -e):# 每月第一个周一的凌晨2点执行脚本 0 2 * * 1 [ "$(date +\%d)" -le 7 ] && /path/to/your/backup_script.sh复制到归档服务器:筛选出文件后,用
rsync或scp复制,推荐rsync(支持断点续传、增量同步):# 遍历筛选出的文件,复制到归档服务器 for file in "${latest_files[@]}"; do rsync -avz "$file" user@归档服务器IP:/path/to/archive/dir/ done错误处理与日志:新手脚本建议添加日志记录和错误判断,比如:
# 定义日志文件路径 LOG_FILE="/var/log/backup_sync.log" # 输出到日志 echo "$(date '+%Y-%m-%d %H:%M:%S') 开始同步备份文件" >> "$LOG_FILE" # 复制时判断是否成功 if rsync -avz "$file" user@归档服务器IP:/path/to/archive/dir/; then echo "$(date '+%Y-%m-%d %H:%M:%S') 成功复制文件: $file" >> "$LOG_FILE" else echo "$(date '+%Y-%m-%d %H:%M:%S') 复制失败: $file" >> "$LOG_FILE" exit 1 fi大小写兼容:如果服务器名存在大小写差异(比如示例中的
Webserver和WebServer),可以将服务器标识转为小写统一分组,修改server_id的提取逻辑:server_id=$(echo "$file" | sed -n 's/\(.*D\).*/\1/p' | sed 's/D$//' | tr '[:upper:]' '[:lower:]')
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

