- 添加 Harbor 快速恢复脚本 (harbor-quick-restore.sh) - 添加完整恢复指南 (HARBOR-RESTORE-GUIDE.md) - 添加版本信息文件 (VERSION.md) - 更新 .gitignore 排除敏感数据 - 配置 harbor git remote - 修复 Cloudflare Tunnel 配置 系统重装后可通过以下命令快速恢复: git clone http://192.168.1.83:33000/gao/ljwx-harbor.git cd ljwx-harbor ./harbor-quick-restore.sh
328 lines
8.1 KiB
Bash
Executable File
328 lines
8.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ========================================
|
|
# Homebrew 备份验证工具
|
|
# 功能:验证备份文件完整性和有效性
|
|
# ========================================
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
OPS_DIR="${HOME}/ops"
|
|
BACKUP_DIR="${OPS_DIR}/backups"
|
|
|
|
# 颜色输出
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
RED='\033[0;31m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${GREEN}✓${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
|
log_error() { echo -e "${RED}✗${NC} $1"; }
|
|
log_section() { echo -e "${BLUE}━━━${NC} $1"; }
|
|
|
|
# 验证 Brewfile
|
|
verify_brewfile() {
|
|
local brewfile="$1"
|
|
|
|
log_section "验证 Brewfile: $(basename "$brewfile")"
|
|
|
|
# 检查文件是否存在
|
|
if [ ! -f "$brewfile" ]; then
|
|
log_error "文件不存在"
|
|
return 1
|
|
fi
|
|
|
|
# 检查文件是否为空
|
|
if [ ! -s "$brewfile" ]; then
|
|
log_error "文件为空"
|
|
return 1
|
|
fi
|
|
|
|
# 文件大小
|
|
local size=$(du -h "$brewfile" | cut -f1)
|
|
log_info "文件大小: $size"
|
|
|
|
# 统计内容
|
|
local brew_count=$(grep -c "^brew " "$brewfile" 2>/dev/null || echo 0)
|
|
local cask_count=$(grep -c "^cask " "$brewfile" 2>/dev/null || echo 0)
|
|
local tap_count=$(grep -c "^tap " "$brewfile" 2>/dev/null || echo 0)
|
|
|
|
echo " - Formulae: $brew_count"
|
|
echo " - Casks: $cask_count"
|
|
echo " - Taps: $tap_count"
|
|
|
|
# 基本语法检查
|
|
local errors=0
|
|
|
|
# 检查是否有明显的语法错误
|
|
if grep -q "^[^#]*Error" "$brewfile" 2>/dev/null; then
|
|
log_warn "可能包含错误信息"
|
|
errors=$((errors + 1))
|
|
fi
|
|
|
|
# 检查基本格式
|
|
if ! grep -q "^brew\|^cask\|^tap\|^#" "$brewfile" 2>/dev/null; then
|
|
log_warn "格式可能不正确"
|
|
errors=$((errors + 1))
|
|
fi
|
|
|
|
if [ $errors -eq 0 ]; then
|
|
log_info "Brewfile 格式正确"
|
|
return 0
|
|
else
|
|
log_warn "发现 $errors 个潜在问题"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 验证压缩包
|
|
verify_archive() {
|
|
local archive="$1"
|
|
|
|
log_section "验证压缩包: $(basename "$archive")"
|
|
|
|
# 检查文件是否存在
|
|
if [ ! -f "$archive" ]; then
|
|
log_error "文件不存在"
|
|
return 1
|
|
fi
|
|
|
|
# 文件大小
|
|
local size=$(du -h "$archive" | cut -f1)
|
|
log_info "文件大小: $size"
|
|
|
|
# 测试压缩包完整性
|
|
if tar -tzf "$archive" > /dev/null 2>&1; then
|
|
log_info "压缩包完整"
|
|
|
|
# 列出内容
|
|
echo " 内容:"
|
|
tar -tzf "$archive" | sed 's/^/ /'
|
|
|
|
return 0
|
|
else
|
|
log_error "压缩包损坏"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 比较两个 Brewfile
|
|
compare_brewfiles() {
|
|
local file1="$1"
|
|
local file2="$2"
|
|
|
|
log_section "比较 Brewfile"
|
|
echo " 文件1: $(basename "$file1")"
|
|
echo " 文件2: $(basename "$file2")"
|
|
echo
|
|
|
|
if [ ! -f "$file1" ] || [ ! -f "$file2" ]; then
|
|
log_error "文件不存在"
|
|
return 1
|
|
fi
|
|
|
|
# 提取包列表
|
|
local temp1=$(mktemp)
|
|
local temp2=$(mktemp)
|
|
|
|
grep "^brew\|^cask" "$file1" | sort > "$temp1"
|
|
grep "^brew\|^cask" "$file2" | sort > "$temp2"
|
|
|
|
# 统计差异
|
|
local added=$(comm -13 "$temp1" "$temp2" | wc -l | tr -d ' ')
|
|
local removed=$(comm -23 "$temp1" "$temp2" | wc -l | tr -d ' ')
|
|
local common=$(comm -12 "$temp1" "$temp2" | wc -l | tr -d ' ')
|
|
|
|
echo " 共同包: $common"
|
|
echo " 新增包: $added"
|
|
echo " 移除包: $removed"
|
|
|
|
if [ $added -gt 0 ]; then
|
|
echo
|
|
echo " 新增的包:"
|
|
comm -13 "$temp1" "$temp2" | sed 's/^/ /'
|
|
fi
|
|
|
|
if [ $removed -gt 0 ]; then
|
|
echo
|
|
echo " 移除的包:"
|
|
comm -23 "$temp1" "$temp2" | sed 's/^/ /'
|
|
fi
|
|
|
|
rm -f "$temp1" "$temp2"
|
|
}
|
|
|
|
# 验证所有备份
|
|
verify_all() {
|
|
log_section "验证所有备份文件"
|
|
echo
|
|
|
|
# 验证最新快照
|
|
if [ -f "${BACKUP_DIR}/Brewfile.latest" ]; then
|
|
verify_brewfile "${BACKUP_DIR}/Brewfile.latest"
|
|
echo
|
|
else
|
|
log_warn "未找到 Brewfile.latest"
|
|
echo
|
|
fi
|
|
|
|
# 验证最近的 Brewfile 备份
|
|
echo "最近的 Brewfile 备份:"
|
|
local brewfiles=$(find "$BACKUP_DIR" -name "Brewfile_*.brew" -type f | sort -r | head -5)
|
|
|
|
if [ -n "$brewfiles" ]; then
|
|
local count=0
|
|
while IFS= read -r file; do
|
|
count=$((count + 1))
|
|
echo "[$count] $(basename "$file") - $(ls -lh "$file" | awk '{print $5}')"
|
|
done <<< "$brewfiles"
|
|
echo
|
|
else
|
|
log_warn "未找到 Brewfile 备份"
|
|
echo
|
|
fi
|
|
|
|
# 验证最近的压缩包备份
|
|
echo "最近的压缩包备份:"
|
|
local archives=$(find "$BACKUP_DIR" -name "brew_backup_*.tar.gz" -type f | sort -r | head -5)
|
|
|
|
if [ -n "$archives" ]; then
|
|
local count=0
|
|
while IFS= read -r file; do
|
|
count=$((count + 1))
|
|
echo "[$count] $(basename "$file") - $(ls -lh "$file" | awk '{print $5}')"
|
|
done <<< "$archives"
|
|
echo
|
|
else
|
|
log_warn "未找到压缩包备份"
|
|
echo
|
|
fi
|
|
}
|
|
|
|
# 健康检查
|
|
health_check() {
|
|
log_section "Homebrew 健康检查"
|
|
|
|
# 检查 Homebrew 是否安装
|
|
if command -v brew &> /dev/null; then
|
|
log_info "Homebrew 已安装: $(brew --version | head -n1)"
|
|
else
|
|
log_error "Homebrew 未安装"
|
|
return 1
|
|
fi
|
|
|
|
# 检查备份目录
|
|
if [ -d "$BACKUP_DIR" ]; then
|
|
log_info "备份目录存在: $BACKUP_DIR"
|
|
|
|
local backup_count=$(find "$BACKUP_DIR" -name "Brewfile_*.brew" -type f | wc -l | tr -d ' ')
|
|
echo " - Brewfile 备份: $backup_count 个"
|
|
|
|
local archive_count=$(find "$BACKUP_DIR" -name "brew_backup_*.tar.gz" -type f | wc -l | tr -d ' ')
|
|
echo " - 压缩包备份: $archive_count 个"
|
|
else
|
|
log_warn "备份目录不存在"
|
|
fi
|
|
|
|
# 检查最新快照
|
|
if [ -f "${BACKUP_DIR}/Brewfile.latest" ]; then
|
|
local age=$(find "${BACKUP_DIR}/Brewfile.latest" -mtime +7 2>/dev/null | wc -l | tr -d ' ')
|
|
if [ "$age" -gt 0 ]; then
|
|
log_warn "最新快照超过 7 天未更新"
|
|
else
|
|
log_info "最新快照是最近的"
|
|
fi
|
|
else
|
|
log_warn "未找到最新快照"
|
|
fi
|
|
|
|
# 运行 brew doctor(简化版)
|
|
echo
|
|
log_section "运行 brew doctor"
|
|
if brew doctor 2>&1 | head -20; then
|
|
log_info "Homebrew 状态正常"
|
|
else
|
|
log_warn "Homebrew 可能需要修复"
|
|
fi
|
|
}
|
|
|
|
# 显示帮助
|
|
show_help() {
|
|
cat << 'EOF'
|
|
Homebrew 备份验证工具
|
|
|
|
用法: brew-verify.sh <命令> [参数]
|
|
|
|
命令:
|
|
brewfile <文件> 验证指定的 Brewfile
|
|
archive <文件> 验证指定的压缩包
|
|
compare <文件1> <文件2> 比较两个 Brewfile
|
|
all 验证所有备份文件
|
|
health 健康检查
|
|
help 显示此帮助信息
|
|
|
|
示例:
|
|
# 验证最新快照
|
|
./brew-verify.sh brewfile ~/ops/backups/Brewfile.latest
|
|
|
|
# 验证压缩包
|
|
./brew-verify.sh archive ~/ops/backups/brew_backup_2025-12-28.tar.gz
|
|
|
|
# 比较两个备份
|
|
./brew-verify.sh compare Brewfile.latest Brewfile_2025-12-27.brew
|
|
|
|
# 验证所有备份
|
|
./brew-verify.sh all
|
|
|
|
# 健康检查
|
|
./brew-verify.sh health
|
|
|
|
EOF
|
|
}
|
|
|
|
# 主函数
|
|
main() {
|
|
case "${1:-}" in
|
|
brewfile)
|
|
if [ -z "${2:-}" ]; then
|
|
log_error "请指定 Brewfile 路径"
|
|
exit 1
|
|
fi
|
|
verify_brewfile "$2"
|
|
;;
|
|
archive)
|
|
if [ -z "${2:-}" ]; then
|
|
log_error "请指定压缩包路径"
|
|
exit 1
|
|
fi
|
|
verify_archive "$2"
|
|
;;
|
|
compare)
|
|
if [ -z "${2:-}" ] || [ -z "${3:-}" ]; then
|
|
log_error "请指定两个 Brewfile 路径"
|
|
exit 1
|
|
fi
|
|
compare_brewfiles "$2" "$3"
|
|
;;
|
|
all)
|
|
verify_all
|
|
;;
|
|
health)
|
|
health_check
|
|
;;
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
echo "错误: 未知命令 '${1:-}'"
|
|
echo
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|