Created
September 6, 2025 13:11
-
-
Save xjoker/5b90895036596c532ceef2c89d4f483a to your computer and use it in GitHub Desktop.
用于VPS.Town主机商的A3区域Debian13的Proxmox安装脚本。系统要求安装主机商的Debian13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # | |
| # Proxmox VE on Debian 13 - 优化版单脚本安装 | |
| # 架构重构:大幅精简代码,提升可维护性 | |
| # | |
| set -eo pipefail | |
| # ============================================================================= | |
| # 核心配置和工具函数 | |
| # ============================================================================= | |
| # 调试模式开关(通过环境变量或参数控制) | |
| DEBUG_MODE=${DEBUG:-false} | |
| if [ "$1" = "--debug" ] || [ "$1" = "-d" ]; then | |
| DEBUG_MODE=true | |
| shift # 移除调试参数 | |
| fi | |
| # 输出重定向函数 | |
| run_cmd() { | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| # 调试模式:显示命令和所有输出 | |
| echo -e "\033[0;36m[DEBUG] 执行: $@\033[0m" >&2 | |
| "$@" | |
| else | |
| # 静默模式:隐藏输出 | |
| "$@" >/dev/null 2>&1 | |
| fi | |
| } | |
| # 颜色输出 | |
| log() { echo -e "\033[0;32m[INFO]\033[0m $1"; } | |
| warn() { echo -e "\033[1;33m[WARN]\033[0m $1"; } | |
| error() { echo -e "\033[0;31m[ERROR]\033[0m $1"; exit 1; } | |
| # 默认选择 Yes 的确认函数 | |
| confirm_yes() { | |
| echo -n -e "\033[1;33m[INPUT]\033[0m $1 (Y/n) " | |
| read -n 1 -r | |
| echo | |
| # 默认为 yes(如果用户直接按回车或输入Y/y) | |
| [[ -z "$REPLY" || "$REPLY" =~ ^[Yy]$ ]] | |
| } | |
| # 默认选择 No 的确认函数 | |
| confirm_no() { | |
| echo -n -e "\033[1;33m[INPUT]\033[0m $1 (y/N) " | |
| read -n 1 -r | |
| echo | |
| # 默认为 no(只有明确输入y/Y才返回true) | |
| [[ "$REPLY" =~ ^[Yy]$ ]] | |
| } | |
| # 保留原来的confirm作为默认Yes的别名 | |
| confirm() { confirm_yes "$@"; } | |
| debug() { [ "$DEBUG_MODE" = "true" ] && echo -e "\033[0;36m[DEBUG]\033[0m $1"; } | |
| # 工具可用性检查函数 | |
| check_tool() { | |
| local tool=$1 | |
| local package=${2:-$1} | |
| if ! command -v "$tool" >/dev/null 2>&1; then | |
| warn "工具 $tool 不可用,尝试安装 $package..." | |
| run_cmd apt install -y "$package" || { | |
| error "无法安装 $package,脚本无法继续执行" | |
| } | |
| fi | |
| } | |
| # 系统检查 | |
| check_system() { | |
| [ "$EUID" -eq 0 ] || error "请使用 root 用户运行此脚本" | |
| grep -q "13" /etc/debian_version || { warn "非 Debian 13 系统"; confirm_no "是否继续?" || exit 1; } | |
| } | |
| # 配置收集函数 | |
| collect_config() { | |
| log "收集安装配置..." | |
| # 主机名配置 | |
| CURRENT_HOSTNAME=$(hostname -s) | |
| read -p "新主机名 (留空保持 $CURRENT_HOSTNAME): " NEW_HOSTNAME | |
| NEW_HOSTNAME=${NEW_HOSTNAME:-$CURRENT_HOSTNAME} | |
| # 修复:允许大写字母和更灵活的主机名格式 | |
| if ! [[ "$NEW_HOSTNAME" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$ ]]; then | |
| error "主机名格式无效(只能包含字母、数字和连字符,不能以连字符开头或结尾)" | |
| fi | |
| # GRUB磁盘检测 - 智能检测当前GRUB安装位置 | |
| GRUB_DISKS="" | |
| # 方法1: 通过grub-probe检测 | |
| # 确保 grub-probe 可用 | |
| if command -v grub-probe >/dev/null 2>&1 || check_tool grub-probe grub2-common 2>/dev/null; then | |
| BOOT_DEVICE=$(grub-probe --target=device /boot 2>/dev/null || true) | |
| if [ ! -z "$BOOT_DEVICE" ]; then | |
| # 提取磁盘设备(去除分区号) | |
| if [[ "$BOOT_DEVICE" =~ ^/dev/[sv]d[a-z][0-9]*$ ]]; then | |
| GRUB_DISKS=$(echo "$BOOT_DEVICE" | sed 's/[0-9]*$//') | |
| elif [[ "$BOOT_DEVICE" =~ ^/dev/nvme[0-9]+n[0-9]+p[0-9]+$ ]]; then | |
| GRUB_DISKS=$(echo "$BOOT_DEVICE" | sed 's/p[0-9]*$//') | |
| fi | |
| fi | |
| fi | |
| # 方法2: 如果方法1失败,检查MBR签名 | |
| if [ -z "$GRUB_DISKS" ]; then | |
| check_tool strings binutils | |
| for disk in /dev/sda /dev/vda /dev/nvme0n1; do | |
| if [ -b "$disk" ] && dd if="$disk" bs=512 count=1 2>/dev/null | strings | grep -q "GRUB"; then | |
| GRUB_DISKS="$disk" | |
| break | |
| fi | |
| done | |
| fi | |
| # 方法3: 如果仍未找到,使用第一个可用磁盘 | |
| if [ -z "$GRUB_DISKS" ]; then | |
| check_tool lsblk util-linux | |
| GRUB_DISKS=$(lsblk -d -n -o NAME,TYPE | grep disk | head -1 | awk '{print "/dev/"$1}') | |
| fi | |
| # 确认GRUB安装位置 | |
| if [ -b "$GRUB_DISKS" ]; then | |
| log "检测到GRUB当前安装位置: $GRUB_DISKS" | |
| if ! confirm_yes "确认将GRUB安装到 $GRUB_DISKS?"; then | |
| read -p "输入磁盘路径: " GRUB_DISKS || true | |
| fi | |
| else | |
| warn "无法自动检测GRUB位置" | |
| read -p "请输入GRUB安装磁盘路径 (如 /dev/sda): " GRUB_DISKS || true | |
| fi | |
| # 验证GRUB磁盘路径 | |
| if [ -z "${GRUB_DISKS:-}" ]; then | |
| error "GRUB磁盘路径不能为空" | |
| elif [ ! -b "$GRUB_DISKS" ]; then | |
| error "无效的GRUB磁盘路径: $GRUB_DISKS" | |
| fi | |
| # 8006端口安全配置 | |
| warn "8006端口默认仅允许已建立连接访问" | |
| OPEN_8006_PUBLIC="no" | |
| if confirm_no "是否开放8006到公网?(不推荐)"; then | |
| OPEN_8006_PUBLIC="yes" | |
| warn "请确保使用强密码!" | |
| fi | |
| log "配置收集完成" | |
| } | |
| # 保存/加载配置 | |
| save_config() { | |
| cat > /root/.pve_install_config << EOF | |
| NEW_HOSTNAME="$NEW_HOSTNAME" | |
| GRUB_DISKS="$GRUB_DISKS" | |
| OPEN_8006_PUBLIC="$OPEN_8006_PUBLIC" | |
| STAGE_ONE_COMPLETED="yes" | |
| EOF | |
| } | |
| load_config() { | |
| [ -f /root/.pve_install_config ] && source /root/.pve_install_config | |
| } | |
| # APT操作函数 | |
| setup_pve_repo() { | |
| log "配置 Proxmox VE 仓库..." | |
| # 添加仓库 | |
| cat > /etc/apt/sources.list.d/pve-install-repo.sources << EOF | |
| Types: deb | |
| URIs: http://download.proxmox.com/debian/pve | |
| Suites: trixie | |
| Components: pve-no-subscription | |
| Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg | |
| Architectures: amd64 | |
| EOF | |
| # 下载密钥 | |
| check_tool wget wget | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| wget -O /usr/share/keyrings/proxmox-archive-keyring.gpg \ | |
| https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg || error "无法下载仓库密钥" | |
| else | |
| wget -qO /usr/share/keyrings/proxmox-archive-keyring.gpg \ | |
| https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg || error "无法下载仓库密钥" | |
| fi | |
| debug "更新软件包列表..." | |
| run_cmd apt update | |
| debug "升级软件包..." | |
| run_cmd apt full-upgrade -y | |
| } | |
| # 配置主机名和hosts | |
| setup_hostname() { | |
| [ "$NEW_HOSTNAME" != "$CURRENT_HOSTNAME" ] || return 0 | |
| log "配置主机名: $NEW_HOSTNAME" | |
| hostnamectl set-hostname "$NEW_HOSTNAME" | |
| # 禁用cloud-init hosts管理 & 配置hosts文件(统一处理) | |
| [ -f /etc/cloud/cloud.cfg ] && { | |
| mkdir -p /etc/cloud/cloud.cfg.d | |
| echo "manage_etc_hosts: false" > /etc/cloud/cloud.cfg.d/99-disable-hosts-management.cfg | |
| } | |
| PRIMARY_IP=$(ip route get 1 | awk '{print $7; exit}') | |
| cp /etc/hosts /etc/hosts.bak 2>/dev/null || true | |
| cat > /etc/hosts << EOF | |
| 127.0.0.1 localhost | |
| $PRIMARY_IP $NEW_HOSTNAME | |
| ::1 localhost ip6-localhost ip6-loopback | |
| ff02::1 ip6-allnodes | |
| ff02::2 ip6-allrouters | |
| EOF | |
| log "主机名配置完成: $PRIMARY_IP -> $NEW_HOSTNAME" | |
| } | |
| # 安装PVE内核 | |
| install_pve_kernel() { | |
| log "安装 Proxmox VE 内核..." | |
| # 预配置GRUB | |
| check_tool debconf-set-selections debconf-utils | |
| echo "grub-pc grub-pc/install_devices multiselect $GRUB_DISKS" | debconf-set-selections | |
| echo "grub-pc grub-pc/install_devices_empty boolean false" | debconf-set-selections | |
| # 安装内核 | |
| debug "安装PVE内核包..." | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-default-kernel | |
| else | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-default-kernel >/dev/null 2>&1 | |
| fi || { | |
| warn "内核安装失败,尝试修复..." | |
| debug "运行dpkg --configure -a修复..." | |
| run_cmd dpkg --configure -a | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-default-kernel | |
| else | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-default-kernel >/dev/null 2>&1 | |
| fi || error "PVE内核安装失败" | |
| } | |
| } | |
| # 配置网桥 | |
| setup_network_bridge() { | |
| # 检查vmbr0是否已存在 | |
| if ip addr show vmbr0 >/dev/null 2>&1; then | |
| log "网桥 vmbr0 已存在,跳过网桥配置" | |
| debug "当前vmbr0配置: $(ip addr show vmbr0 | grep 'inet ' | awk '{print $2}' | head -n1)" | |
| # 如果已存在vmbr0,可能之前创建过,仍需检查DNS | |
| BRIDGE_CREATED=true | |
| return 0 | |
| fi | |
| IFACE=$(ip route | grep default | awk '{print $5}' | head -n1) | |
| IP_CIDR=$(ip -4 addr show $IFACE | grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+/\d+' | head -n1) | |
| GATEWAY=$(ip route | grep default | awk '{print $3}' | head -n1) | |
| [ -z "$IFACE" ] || [ -z "$IP_CIDR" ] || [ -z "$GATEWAY" ] && { | |
| warn "无法自动检测网络配置,跳过网桥设置" | |
| return 1 | |
| } | |
| log "配置网络桥接: $IFACE -> vmbr0" | |
| confirm_yes "确认创建网桥?" || return 0 | |
| cp /etc/network/interfaces /etc/network/interfaces.bak | |
| cat > /etc/network/interfaces << EOF | |
| auto lo | |
| iface lo inet loopback | |
| auto $IFACE | |
| iface $IFACE inet manual | |
| auto vmbr0 | |
| iface vmbr0 inet static | |
| address $IP_CIDR | |
| gateway $GATEWAY | |
| bridge-ports $IFACE | |
| bridge-stp off | |
| bridge-fd 0 | |
| bridge-vlan-aware yes | |
| bridge-vids 2-4094 | |
| EOF | |
| debug "重启网络服务..." | |
| run_cmd systemctl restart networking | |
| sleep 2 | |
| if ip addr show vmbr0 | grep -q "$IP_CIDR"; then | |
| log "网桥创建成功" | |
| # 设置标记:创建了网桥,稍后必须修复DNS | |
| BRIDGE_CREATED=true | |
| else | |
| warn "网桥创建可能失败" | |
| BRIDGE_CREATED=false | |
| fi | |
| } | |
| # 防火墙配置模板 | |
| create_firewall_rules() { | |
| log "配置防火墙规则..." | |
| mkdir -p /etc/pve/firewall | |
| # 基础防火墙模板(默认不包含8006规则) | |
| create_fw_file() { | |
| cat << EOF | |
| [OPTIONS] | |
| enable: 1 | |
| policy_in: DROP | |
| policy_out: ACCEPT | |
| log_level_in: info | |
| [RULES] | |
| IN ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED | |
| IN ACCEPT -i lo | |
| IN SSH(ACCEPT) | |
| IN ACCEPT -p icmp | |
| EOF | |
| } | |
| # 仅当用户明确选择时才添加8006规则 | |
| if [ "$OPEN_8006_PUBLIC" = "yes" ]; then | |
| create_fw_file_with_8006() { | |
| cat << EOF | |
| [OPTIONS] | |
| enable: 1 | |
| policy_in: DROP | |
| policy_out: ACCEPT | |
| log_level_in: info | |
| [RULES] | |
| IN ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED | |
| IN ACCEPT -i lo | |
| IN SSH(ACCEPT) | |
| IN ACCEPT -p tcp --dport 8006 | |
| IN ACCEPT -p icmp | |
| EOF | |
| } | |
| create_fw_file_with_8006 > /etc/pve/firewall/cluster.fw | |
| create_fw_file_with_8006 > /etc/pve/host.fw | |
| log "8006端口: 公网开放模式" | |
| else | |
| create_fw_file > /etc/pve/firewall/cluster.fw | |
| create_fw_file > /etc/pve/host.fw | |
| log "8006端口: 安全模式(无公网访问规则)" | |
| fi | |
| } | |
| # PVE集群服务管理 | |
| manage_pve_services() { | |
| log "管理 Proxmox VE 服务..." | |
| # 关键修复:清理FUSE挂载点冲突 | |
| if [ -d /etc/pve ] && [ "$(ls -A /etc/pve 2>/dev/null)" ]; then | |
| warn "修复FUSE挂载点冲突..." | |
| debug "停止PVE服务..." | |
| run_cmd systemctl stop pve-cluster pvedaemon pvestatd pveproxy || true | |
| debug "卸载/etc/pve..." | |
| run_cmd umount /etc/pve || true | |
| mv /etc/pve /etc/pve.backup.$(date +%s) | |
| mkdir -p /etc/pve | |
| fi | |
| # 启动pve-cluster | |
| systemctl start pve-cluster || { | |
| warn "pve-cluster启动失败,执行修复..." | |
| rm -f /var/lib/pve-cluster/.pmxcfs.lockfile | |
| rm -rf /var/lib/pve-cluster/config.db* | |
| chown -R root:www-data /var/lib/pve-cluster/ | |
| sleep 2 | |
| systemctl start pve-cluster || error "pve-cluster无法启动" | |
| } | |
| sleep 3 | |
| # 生成SSL证书 | |
| systemctl is-active --quiet pve-cluster && { | |
| debug "生成SSL证书..." | |
| run_cmd pvecm updatecerts --force | |
| create_firewall_rules | |
| log "SSL证书和防火墙配置完成" | |
| } | |
| # 启动其他服务 | |
| for service in pvedaemon pvestatd pveproxy pve-firewall; do | |
| debug "启用并启动 $service..." | |
| run_cmd systemctl enable $service | |
| run_cmd systemctl restart $service && log "$service 启动成功" || warn "$service 启动失败" | |
| done | |
| } | |
| # DNS修复函数(独立函数,在所有任务最后执行) | |
| fix_dns() { | |
| log "检查DNS解析状态..." | |
| check_tool nslookup dnsutils | |
| # 如果创建了网桥,强制进行DNS修复(网桥创建会导致DNS丢失) | |
| if [ "${BRIDGE_CREATED:-false}" = "true" ]; then | |
| warn "检测到网桥已创建,强制执行DNS修复(网桥创建通常导致DNS失效)" | |
| else | |
| # 只有未创建网桥时才进行DNS检测 | |
| debug "未创建网桥,检测DNS状态..." | |
| # 多重测试DNS解析 | |
| dns_working=false | |
| # 测试1: 使用nslookup | |
| if nslookup google.com >/dev/null 2>&1; then | |
| debug "nslookup测试通过" | |
| # 测试2: 使用ping确认实际连通性 | |
| if ping -c 1 -W 3 google.com >/dev/null 2>&1; then | |
| debug "ping测试通过" | |
| dns_working=true | |
| else | |
| debug "ping测试失败,虽然nslookup成功" | |
| fi | |
| else | |
| debug "nslookup测试失败" | |
| fi | |
| if [ "$dns_working" = "true" ]; then | |
| log "DNS解析正常,无需修复" | |
| return 0 | |
| fi | |
| fi | |
| warn "检测到DNS解析失败,开始修复..." | |
| debug "备份原始DNS配置..." | |
| cp /etc/systemd/resolved.conf /etc/systemd/resolved.conf.bak 2>/dev/null || true | |
| debug "配置systemd-resolved DNS服务器..." | |
| cat > /etc/systemd/resolved.conf << 'EOF' | |
| [Resolve] | |
| DNS=1.1.1.1 104.234.20.6 | |
| FallbackDNS=8.8.8.8 8.8.4.4 | |
| Domains=~. | |
| DNSSEC=no | |
| DNSOverTLS=no | |
| EOF | |
| debug "重启systemd-resolved服务..." | |
| run_cmd systemctl restart systemd-resolved | |
| # 等待服务重启完成 | |
| sleep 3 | |
| # 验证DNS修复效果(使用相同的多重测试) | |
| dns_fixed=false | |
| # 重新测试DNS解析 | |
| if nslookup google.com >/dev/null 2>&1; then | |
| debug "修复后nslookup测试通过" | |
| # 验证ping连通性 | |
| if ping -c 1 -W 3 google.com >/dev/null 2>&1; then | |
| debug "修复后ping测试通过" | |
| dns_fixed=true | |
| else | |
| debug "修复后ping仍然失败" | |
| fi | |
| else | |
| debug "修复后nslookup仍然失败" | |
| fi | |
| if [ "$dns_fixed" = "true" ]; then | |
| log "DNS配置修复成功" | |
| return 0 | |
| else | |
| warn "DNS修复未完全生效,可能需要重启系统" | |
| log "您可以尝试手动运行: systemctl restart systemd-resolved" | |
| return 1 | |
| fi | |
| } | |
| # 系统优化 | |
| optimize_system() { | |
| log "系统优化..." | |
| # 清理旧内核 | |
| kernels_to_remove=$(dpkg -l | grep -E "linux-image-[0-9]" | grep -v "$(uname -r)" | grep -v "pve" | awk '{print $2}') | |
| [ -n "$kernels_to_remove" ] && { | |
| log "清理旧内核: $kernels_to_remove" | |
| debug "移除内核包..." | |
| run_cmd apt remove -y linux-image-amd64 $kernels_to_remove | |
| } | |
| # 更新GRUB并移除os-prober | |
| if [ -d /boot/grub ]; then | |
| debug "更新GRUB配置..." | |
| check_tool update-grub grub2-common | |
| run_cmd update-grub | |
| fi | |
| if dpkg -l | grep -q os-prober; then | |
| debug "移除os-prober..." | |
| run_cmd apt remove -y os-prober | |
| fi | |
| # 恢复IPv6并刷新软件源 | |
| debug "恢复IPv6..." | |
| run_cmd sysctl -w net.ipv6.conf.all.disable_ipv6=0 | |
| run_cmd sysctl -w net.ipv6.conf.default.disable_ipv6=0 | |
| debug "刷新软件源..." | |
| run_cmd apt update || true | |
| } | |
| # 临时文件清理函数 | |
| cleanup_temp_files() { | |
| debug "清理临时文件和配置..." | |
| # 清理脚本创建的临时文件 | |
| local temp_files=( | |
| "/root/.pve_install_config" # 脚本配置文件 | |
| "/etc/systemd/resolved.conf.bak" # DNS配置备份 | |
| "/etc/hosts.bak" # hosts文件备份 | |
| "/etc/network/interfaces.bak" # 网络配置备份 | |
| "/etc/pve.backup.*" # PVE挂载点备份 | |
| "/tmp/pve-install-*" # 可能的临时目录 | |
| ) | |
| for file_pattern in "${temp_files[@]}"; do | |
| if [[ "$file_pattern" == *"*"* ]]; then | |
| # 处理通配符模式 | |
| for file in $file_pattern; do | |
| [ -e "$file" ] && { | |
| debug "删除临时文件: $file" | |
| rm -rf "$file" 2>/dev/null || true | |
| } | |
| done | |
| else | |
| # 处理普通文件 | |
| [ -e "$file_pattern" ] && { | |
| debug "删除临时文件: $file_pattern" | |
| rm -f "$file_pattern" 2>/dev/null || true | |
| } | |
| fi | |
| done | |
| # 清理APT缓存和临时包 | |
| debug "清理APT缓存..." | |
| run_cmd apt autoremove -y || true | |
| run_cmd apt autoclean || true | |
| log "临时文件清理完成" | |
| } | |
| # 安装完成报告 | |
| installation_complete() { | |
| IP_ADDR=$(hostname -I | awk '{print $1}') | |
| log "========================================" | |
| log "Proxmox VE 安装完成!" | |
| log "========================================" | |
| log "Web界面: https://$IP_ADDR:8006/" | |
| log "用户名: root" | |
| log "密码: 您的root密码" | |
| if [ "$OPEN_8006_PUBLIC" = "yes" ]; then | |
| warn "8006端口已开放到公网,请确保使用强密码!" | |
| else | |
| log "8006端口仅允许已建立连接访问(推荐)" | |
| log "如需公网访问,请配置SSH隧道或修改防火墙规则" | |
| fi | |
| log "========================================" | |
| # 清理所有临时文件和配置 | |
| cleanup_temp_files | |
| } | |
| # ============================================================================= | |
| # 主程序流程 | |
| # ============================================================================= | |
| main() { | |
| # 初始化全局变量 | |
| BRIDGE_CREATED=false | |
| # 显示调试模式状态 | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| log "调试模式已启用 - 将显示所有命令输出" | |
| else | |
| log "静默模式运行 - 使用 --debug 或 -d 参数查看详细输出" | |
| fi | |
| check_system | |
| # 检测执行阶段 | |
| current_kernel=$(uname -r) | |
| if echo "$current_kernel" | grep -q "pve"; then | |
| # 第二阶段:PVE软件包安装 | |
| log "第二阶段:PVE软件包安装" | |
| load_config | |
| # 临时禁用IPv6 | |
| debug "临时禁用IPv6..." | |
| run_cmd sysctl -w net.ipv6.conf.all.disable_ipv6=1 | |
| # 安装PVE软件包 | |
| echo "postfix postfix/main_mailer_type select Local only" | debconf-set-selections | |
| debug "安装核心PVE软件包..." | |
| if [ "$DEBUG_MODE" = "true" ]; then | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-ve postfix open-iscsi chrony bridge-utils ifupdown2 | |
| else | |
| DEBIAN_FRONTEND=noninteractive apt install -y proxmox-ve postfix open-iscsi chrony bridge-utils ifupdown2 >/dev/null 2>&1 | |
| fi | |
| debug "安装额外网络组件..." | |
| run_cmd apt install -y libpve-network-perl frr-pythontools dnsmasq | |
| optimize_system | |
| setup_hostname # 第二阶段处理hosts | |
| setup_network_bridge | |
| manage_pve_services | |
| # 所有任务完成后最后执行DNS修复 | |
| fix_dns | |
| installation_complete | |
| else | |
| # 第一阶段:PVE内核安装 | |
| log "第一阶段:PVE内核安装" | |
| collect_config | |
| save_config | |
| debug "安装基础依赖包..." | |
| run_cmd apt update || error "apt update 失败" | |
| # 安装脚本必需的工具包 | |
| REQUIRED_PACKAGES="bc gpg gnupg vim curl wget sudo systemd-resolved ifupdown2 dnsutils grub2-common binutils debconf-utils bridge-utils lsb-release" | |
| debug "安装必需工具包: $REQUIRED_PACKAGES" | |
| run_cmd apt install -y $REQUIRED_PACKAGES || { | |
| warn "部分依赖包安装失败,尝试分批安装..." | |
| # 核心包优先安装 | |
| run_cmd apt install -y bc gpg gnupg curl wget sudo systemd-resolved || error "核心依赖包安装失败" | |
| # 网络工具 | |
| run_cmd apt install -y dnsutils || warn "DNS工具安装失败,可能影响DNS验证" | |
| # GRUB工具 | |
| run_cmd apt install -y grub2-common || warn "GRUB工具安装失败,可能影响内核检测" | |
| # 其他工具 | |
| run_cmd apt install -y binutils debconf-utils bridge-utils lsb-release ifupdown2 vim || warn "部分工具安装失败,继续执行..." | |
| } | |
| setup_pve_repo || error "PVE仓库配置失败" | |
| install_pve_kernel || error "PVE内核安装失败" | |
| log "========================================" | |
| log "第一阶段完成!" | |
| log "========================================" | |
| log "请重启系统到PVE内核,然后再次运行此脚本完成安装" | |
| log "重启命令: systemctl reboot" | |
| log "重启后运行: $0" | |
| log "========================================" | |
| fi | |
| } | |
| # 执行主程序 | |
| main "$@" || { | |
| error_code=$? | |
| error "脚本执行失败,错误代码: $error_code" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment