This commit is contained in:
2025-11-18 10:38:19 +08:00
commit 87c05d684d
10 changed files with 4762 additions and 0 deletions

298
install_patch_system.sh Normal file
View File

@@ -0,0 +1,298 @@
#!/bin/bash
# install_patch_system.sh - 补丁管理系统安装脚本
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="/opt/patch-management"
CONFIG_FILE="${SCRIPT_DIR}/patch_config.sh"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"; }
info() { log "INFO: $1"; }
error() { log "ERROR: $1"; exit 1; }
warn() { log "WARNING: $1"; }
# 检测是否在Docker容器中运行
is_docker_environment() {
# 检查多种Docker环境标识
if [[ -f /.dockerenv ]]; then
return 0
fi
if grep -q docker /proc/1/cgroup 2>/dev/null; then
return 0
fi
if grep -q lxc /proc/1/cgroup 2>/dev/null; then
return 0
fi
if [[ -n "${container:-}" ]]; then
return 0
fi
if [[ -n "${DOCKER_CONTAINER:-}" ]]; then
return 0
fi
# 检查容器相关的环境变量组合
local env_vars=(
"HOSTNAME"
"HOME"
"USER"
)
for var in "${env_vars[@]}"; do
if [[ -n "${!var:-}" ]] && [[ "${!var}" =~ ^[a-f0-9]{12,}$ ]]; then
# 检查环境变量值是否像容器ID
if [[ ${!var} =~ ^[a-f0-9]{12,64}$ ]]; then
return 0
fi
fi
done
return 1
}
# 获取适当的命令前缀在Docker中使用空前缀否则使用sudo
get_cmd_prefix() {
if is_docker_environment; then
echo ""
else
echo "sudo"
fi
}
# 配置加载
load_config() {
if [[ ! -f "$CONFIG_FILE" ]]; then
error "配置文件不存在: $CONFIG_FILE"
exit 1
fi
source "$CONFIG_FILE"
info "配置文件加载完成"
}
install_dependencies() {
info "安装系统依赖..."
local sudo_prefix
sudo_prefix=$(get_cmd_prefix)
local will_install_dependencies=false
local dependencies=(
"tar"
"gzip"
"bzip2"
"jq"
"gpg"
"bc"
)
for dep in "${dependencies[@]}"; do
if command -v "$dep" >/dev/null 2>&1; then
info "系统依赖 $dep 已安装"
else
warn "系统依赖 $dep 未安装"
will_install_dependencies=true
fi
done
if ! $will_install_dependencies; then
info "系统依赖已安装"
return 0
fi
# 关键依赖
local keys_deps=(
"coreutils"
"findutils"
"util-linux"
)
if command -v apt-get >/dev/null 2>&1; then
# Debian/Ubuntu
$sudo_prefix apt-get update
$sudo_prefix apt-get install -y $(printf "%s " "${keys_deps[@]}") $(printf "%s " "${dependencies[@]}")
elif command -v yum >/dev/null 2>&1; then
# CentOS/RHEL
$sudo_prefix yum install -y $(printf "%s " "${keys_deps[@]}") $(printf "%s " "${dependencies[@]}")
else
warn "无法自动安装依赖,请手动安装: $(printf "%s " "${keys_deps[@]}") $(printf "%s " "${dependencies[@]}")"
fi
# 安装GPG用于签名验证
if command -v apt-get >/dev/null 2>&1; then
$sudo_prefix apt-get install -y gnupg
elif command -v yum >/dev/null 2>&1; then
$sudo_prefix yum install -y gnupg
fi
}
create_directories() {
info "创建目录结构..."
local sudo_prefix
sudo_prefix=$(get_cmd_prefix)
$sudo_prefix mkdir -p "$INSTALL_DIR"
$sudo_prefix mkdir -p "/var/backups/patch"
$sudo_prefix mkdir -p "/var/log/patch_system"
$sudo_prefix mkdir -p "/etc/patch/keys"
# 设置权限
$sudo_prefix chmod 755 "$INSTALL_DIR"
$sudo_prefix chmod 755 "/var/backups/patch"
$sudo_prefix chmod 755 "/var/log/patch_system"
$sudo_prefix chmod 700 "/etc/patch/keys"
}
install_scripts() {
info "安装脚本文件..."
local sudo_prefix
sudo_prefix=$(get_cmd_prefix)
# 复制脚本文件, 存在则覆盖
$sudo_prefix cp --force "$SCRIPT_DIR/patch_generator.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_fnc.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_applier.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_rollback.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_verifier.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_workflow.sh" "$INSTALL_DIR/"
$sudo_prefix cp --force "$SCRIPT_DIR/patch_config.sh" "$INSTALL_DIR/"
info "脚本文件已安装在: $INSTALL_DIR/"
# 设置执行权限
$sudo_prefix chmod +x "$INSTALL_DIR"/*.sh
# 创建符号链接
$sudo_prefix ln -sf "$INSTALL_DIR/patch_workflow.sh" "/usr/local/bin/patch-mgmt"
info "符号链接已创建: /usr/local/bin/patch-mgmt"
}
setup_cron() {
info "设置定时任务..."
if is_docker_environment; then
info "Docker环境跳过系统定时任务设置"
info "如需定时任务请考虑使用宿主机的crontab或Docker运行参数"
return 0
fi
local sudo_prefix
sudo_prefix=$(get_cmd_prefix)
local cron_job="0 2 * * * $INSTALL_DIR/patch_verifier.sh /opt/patches batch > /var/log/patch_system/batch_verify.log 2>&1"
if ! crontab -l 2>/dev/null | grep -q "patch_verifier.sh"; then
(crontab -l 2>/dev/null; echo "$cron_job") | crontab -
info "定时任务已添加"
else
info "定时任务已存在"
fi
}
generate_gpg_key() {
local name="${1:-John Doe}"
local email="${2:-johndoe@example.com}"
local key_type="${3:-RSA}"
local key_length="${4:-4096}"
cat > /tmp/gpg_batch << EOF
Key-Type: $key_type
Key-Length: $key_length
Subkey-Type: $key_type
Subkey-Length: $key_length
Name-Real: $name
Name-Email: $email
Expire-Date: 0
%commit
EOF
gpg --batch --generate-key /tmp/gpg_batch
rm -f /tmp/gpg_batch
echo "✅ 密钥生成完成"
gpg --list-secret-keys --keyid-format LONG "$email"
}
generate_keys() {
info "生成签名密钥..."
local key_dir="/etc/patch/keys"
local sudo_prefix
sudo_prefix=$(get_cmd_prefix)
if [[ ! -f "$key_dir/private.pem" ]]; then
$sudo_prefix mkdir -p "$key_dir"
# 生成GPG密钥对
generate_gpg_key "$PATCH_AUTHOR" "$PATCH_EMAIL" "RSA" "4096"
# 生成RSA密钥对
openssl genrsa -out "$key_dir/private.pem" 4096
openssl rsa -in "$key_dir/private.pem" -pubout -out "$key_dir/public.pem"
$sudo_prefix chmod 600 "$key_dir/private.pem"
$sudo_prefix chmod 644 "$key_dir/public.pem"
info "密钥对已生成: $key_dir/"
else
info "密钥对已存在"
fi
}
main() {
info "开始安装企业级补丁管理系统"
echo "========================================"
echo "📋 安装配置文件: $INSTALL_DIR/patch_config.sh"
# 加载配置
load_config
# 检查运行环境
if is_docker_environment; then
info "检测到Docker容器环境将以root权限执行不适用sudo"
SUDO_CMD=""
else
info "检测到主机环境将使用sudo执行管理员操作"
SUDO_CMD="sudo"
# 在非Docker环境中建议非root用户运行
if [[ $EUID -eq 0 ]]; then
warn "检测到以root用户运行建议在非Docker环境中使用具备sudo权限的普通用户"
fi
fi
# 安装依赖
install_dependencies
# 创建目录
create_directories
# 安装脚本
install_scripts
# 设置定时任务
setup_cron
# 生成密钥
generate_keys
info "🎉 补丁管理系统安装完成!"
echo ""
echo "📁 安装目录: $INSTALL_DIR"
echo "🔧 使用命令: patch-mgmt"
echo "📋 配置文件: $INSTALL_DIR/patch_config.sh"
echo ""
echo "💡 下一步操作:"
echo " 1. 编辑配置文件: $INSTALL_DIR/patch_config.sh"
echo " 2. 测试系统: patch-mgmt --help"
echo " 3. 配置通知: 修改SLACK_WEBHOOK等设置"
}
main "$@"