wei/sh/MD5.sh
2026-06-26 10:10:40 +08:00

204 lines
6.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
# ================================================
# KR数据同步后 MD5 校验与重试脚本
# 功能:对比源目录与远程目标目录的 MD5基于相对路径不一致则重新同步
# 用法:./kr_data_sync_verify.sh [YYYYMMDD]
# ================================================
# ---------- 配置参数 ----------
#SRC_BASE="/home/sysop/kr_md_save_pkt_loss_v5/data/stockdata" #南方
SRC_BASE="/home/sysop/kr_md_save_centos7_9_20260317/data/stockdata" #金桥
DEST_HOST="swdata@119.167.194.234"
DEST_PORT="60000"
#DEST_BASE="/mnt/data1/data_new_nf/data/stockdata" #南方
DEST_BASE="/mnt/data1/data_new/data/stockdata" #金桥
DEST_MARK_BASE="/mnt/data1/md5"
SSH_OPTS="-o ConnectTimeout=30 -o BatchMode=yes -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ServerAliveCountMax=3"
LOG_DIR="/var/log/kr_data_sync"
LOG_FILE="$LOG_DIR/verify_$(date +%Y%m%d).log"
MAX_RETRIES=10
mkdir -p "$LOG_DIR"
# ---------- 日志函数 ----------
log_info() {
echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" | tee -a "$LOG_FILE"
}
log_error() {
echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $1" | tee -a "$LOG_FILE"
}
usage() {
echo "用法: $0 [YYYYMMDD]"
exit 1
}
check_dependencies() {
command -v rsync &>/dev/null || { log_error "请安装 rsync"; exit 1; }
command -v md5sum &>/dev/null || { log_error "请安装 md5sum"; exit 1; }
}
check_ssh() {
log_info "检查 SSH 连接..."
ssh -p "$DEST_PORT" $SSH_OPTS "$DEST_HOST" "echo ok" &>/dev/null || {
log_error "SSH 连接失败"
exit 1
}
log_info "SSH 连接正常"
}
check_remote_md5sum() {
ssh -p "$DEST_PORT" $SSH_OPTS "$DEST_HOST" "command -v md5sum" &>/dev/null || {
log_error "远程主机缺少 md5sum"
exit 1
}
log_info "远程 md5sum 可用"
}
ensure_remote_mark_dir() {
ssh -p "$DEST_PORT" $SSH_OPTS "$DEST_HOST" "mkdir -p '$DEST_MARK_BASE'" &>/dev/null || {
log_error "无法创建远程标记目录 $DEST_MARK_BASE"
exit 1
}
log_info "远程标记目录已确认: $DEST_MARK_BASE"
}
# ========== 生成相对路径的 MD5 列表 ==========
generate_local_md5() {
local dir="$1"
local tmpfile=$(mktemp)
# 进入源目录,使用相对路径(以 ./ 开头)
(cd "$dir" && find . -type f -print0 2>/dev/null | xargs -0 md5sum 2>/dev/null | sort -k2) > "$tmpfile"
echo "$tmpfile"
}
generate_remote_md5() {
local dir="$1"
local tmpfile=$(mktemp)
# 远程进入目标目录,同样使用相对路径
ssh -p "$DEST_PORT" $SSH_OPTS "$DEST_HOST" "cd '$dir' && find . -type f -print0 2>/dev/null | xargs -0 md5sum 2>/dev/null | sort -k2" > "$tmpfile" 2>/dev/null
echo "$tmpfile"
}
# ====================================================
compare_md5() {
local local_list="$1"
local remote_list="$2"
local diff_file=$(mktemp)
if [ ! -s "$local_list" ]; then
log_error "本地文件列表为空"
rm -f "$diff_file"
return 1
fi
if diff "$local_list" "$remote_list" > "$diff_file" 2>&1; then
log_info "MD5 校验一致"
rm -f "$diff_file"
return 0
else
log_error "MD5 校验不一致,差异如下:"
cat "$diff_file" | tee -a "$LOG_FILE"
rm -f "$diff_file"
return 1
fi
}
do_sync() {
local src="$1"
local dest="$2"
log_info "开始同步: $src -> $dest"
rsync -avz --progress --delete \
-e "ssh -p $DEST_PORT $SSH_OPTS" \
"$src/" \
"$DEST_HOST:$dest/" 2>&1 | tee -a "$LOG_FILE"
local sync_result=${PIPESTATUS[0]}
if [ $sync_result -eq 0 ]; then
log_info "同步完成"
return 0
else
log_error "同步失败,退出码: $sync_result"
return 1
fi
}
create_mark_file() {
local date_str="$1"
#local remote_mark_file="$DEST_MARK_BASE/${date_str}_nf" #南方
local remote_mark_file="$DEST_MARK_BASE/${date_str}_jq" #金桥
echo "Sync completed and verified at $(date -u '+%Y-%m-%d %H:%M:%S UTC')" | \
ssh -p "$DEST_PORT" $SSH_OPTS "$DEST_HOST" "cat > '$remote_mark_file'"
if [ $? -eq 0 ]; then
log_info "已创建标记文件: $remote_mark_file"
else
log_error "创建标记文件失败"
exit 1
fi
}
main() {
local target_date="$1"
[ -z "$target_date" ] && target_date=$(date +%Y%m%d)
if ! [[ "$target_date" =~ ^[0-9]{8}$ ]]; then
log_error "日期格式必须为 YYYYMMDD"
usage
fi
local src_dir="$SRC_BASE/$target_date"
local dest_dir="$DEST_BASE/$target_date"
local remote_mark_file="$DEST_MARK_BASE/$target_date"
log_info "========== 开始 MD5 校验与同步任务 =========="
log_info "日期: $target_date"
log_info "源目录: $src_dir"
log_info "目标目录: $dest_dir"
log_info "标记文件: $remote_mark_file"
[ ! -d "$src_dir" ] && { log_error "源目录不存在: $src_dir"; exit 1; }
check_dependencies
check_ssh
check_remote_md5sum
ensure_remote_mark_dir
local retry_count=0
local success=false
while [ $retry_count -lt $MAX_RETRIES ]; do
retry_count=$((retry_count + 1))
log_info "===== 第 $retry_count 次校验 ====="
local local_md5=$(generate_local_md5 "$src_dir")
local remote_md5=$(generate_remote_md5 "$dest_dir")
if compare_md5 "$local_md5" "$remote_md5"; then
success=true
rm -f "$local_md5" "$remote_md5"
break
else
rm -f "$local_md5" "$remote_md5"
log_info "MD5 不一致,执行同步..."
if ! do_sync "$src_dir" "$dest_dir"; then
log_error "同步失败,终止重试"
exit 1
fi
sleep 5
fi
done
if [ "$success" = true ]; then
log_info "经过 $retry_count 次校验MD5 已一致"
create_mark_file "$target_date"
log_info "任务完成,已生成标记文件"
else
log_error "达到最大重试次数 $MAX_RETRIES,仍然无法使 MD5 一致"
exit 1
fi
log_info "========== 任务结束 =========="
}
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
fi
main "$1"