本文是好吃的糖醋里脊的分享，以及做法需要准备的材料有：里脊肉，玉米淀粉（生粉），鸡蛋，番茄酱，盐，料酒，鸡精，米醋（白醋），食用油做法：先将里脊肉切条使用清水洗净血水装入碗中加上料，酒盐，鸡精抓拌均匀腌制10-15分钟在干净的碗中加入2勺玉米淀粉，一个鸡蛋加入适量的清水搅拌成酸奶糊状物，加入少许食用油再次搅拌将腌制好的里脊肉倒入面糊中搅拌均匀使每条里脊肉都适量裹上淀粉在锅中倒入大量的食用油使用大火加热到7分油热使下入里脊肉（请一条一条的下入）将里脊肉炸制表面金黄即可控干油份捞出再次复炸，复炸至表面出现明显黄褐色后捞出备用锅中留底油使用小火加热倒入1-2勺番茄酱，1勺米醋。1勺盐，1勺白糖使用小火收汁不断搅拌至冒泡状态下入里脊肉条并不断翻炒至表面完全裹满糖醋汁后捞出表面撒上些许白芝麻即可到此你就完成了糖醋里脊的做法下面是我做的时候的照片给你们分享
前言一般大部分人搭建自己的网站这些都是使用的Linux系统配合面板搭建,少部分人使用命令行搭建自己的网站，Linux搭建自己的网站一般都是LNPM和LAPM搭建，Windows系统方面有微软的IIS以及WNPM，因为本人的物理机是使用的Windows Sever 2025但是也不想开虚拟机搭建于是选择直接使用WNPM搭建。WNPM套件-搭建过程WNPM就是Windows+Nginx+PHP+MySQL注意：MySQL使用单独的文章来讲在你的任意目录创建一个Web的文件夹在Nginx的网站和PHP的官网下载Windows可执行程序的版本，PHP一定要使用nts版，如果找不到下载的地方可以在我的资源站进行下载，服务器的上行带宽不高所以有点小慢，[button color="success" icon="" url="https://pan.saklub.ren/" type=""]由川的资源站[/button]进行之后选择Web工具可根据自己的需要进行下载对应的工具和版本，下载完成之后解压并且复制到Web目录创建这几个文件夹[scode type="green" size="small"]SSLLogoWWW[/scode]你的SSL证书放到SSL文件夹里面然后你的Nginx日志和PHP日志都是放Logo文件夹你的网站统一放到WWW文件夹里面这样一个标准的网站架构就好了，以下是我的可以参考PHP配置如果你的PHP是下载的我的，只需要进php的目录修改ini文件中的Logo位置即可基础的php拓展我是安装了 的，如果你是在官网下载的你需要手动修改Logo的储存位置以及手动安装基础拓展和禁用一项配置，这个是我的8.2的配置文件可以作为一个参考[Date] date.timezone=Asia/Shanghai [PHP] max_execution_time=300 extension=pdo_mysql extension=mysqli extension=mbstring extension=openssl extension=fileinfo extension_dir="ext" max_input_time=60 max_input_vars=3000 memory_limit=256M upload_max_filesize=100M post_max_size=100M max_file_uploads=20 display_errors=On display_startup_errors=On log_errors=On cgi.fix_pathinfo=1 html_errors=On error_log=D:\Web\logo\php8.2.9nts.log error_reporting=E_ALL & ~E_NOTICE allow_url_fopen=On allow_url_include=Off Nginx配置现在你的PHP配置已经完成了你现在需要安装并且配置自己的Nginx，你需要打开一下目录编辑Nginx的配置文件 \Web\Nginx1.25.2\conf\nginx.conf 在这个配置文件的 http块内增加一行 include vhosts/*.conf;意思大致是Ngixn启用 vhosts并且将网站的配置文件写在conf文件夹下的 vhosts文件夹内，现在你的Nginx基础的配置也好了
前言我之前的服务器是X79平台的Dell-PowerEdge-R620是比较老旧了但是依然好用，我换的目的是为了更好的性能和更低的功耗服务器选择我选择了Dell-PowerEdge-R640能够使用志强可拓展第一二代的CPU刚好现在内存价格也降了于是与机房沟通之后在机房购买了一台全新的服务器，1U的机器托管费也低性能也够强悍我选择的配置如下因为考虑到我不需要高主频于是我选择了较为便宜的金牌6138*2如果说需要高主频的我就选择铂金系列的CPU了，内存64G刚刚好也不是很浪费综合评定下这个机器还是可以的，无论是从功耗还是架构上都是领先于我那个R620的,这个是CPUZ的基准测试给你给你们作为一个选择服务器的参考原来的服务器因为我已经把硬盘拆掉安装到这个机器上了无法给你们做一个测试，机器的阵列开是后期需要更换成H740Pmini的对于硬盘阵列的读写也是相当大的提升也是对数据安全性的提升以下是老机器的配置后期也是准备下架了总结这次服务器的更新换代也是相当不错的选择也是在内存降价之后的最好选择，同时也为了我们的项目更好的稳定性和状态
前言 本次使用的是KVM+QUME的方案我使用的系统是 Ubuntu 24.04LTS的系统使用apt安装KVM并且配置2个网络一个br0桥接网络一个NAT网络本次使用的所有脚本都会表明出处部署KVM和配置网络环境先使用 bash <(curl -sSL https://linuxmirrors.cn/main.sh)进行换源，然后确认你的CPU支持虚拟化输入以下命令检查,如果不支持请进入BIOS进行开启，支持的话使用下面命令安装KVM套件# 检查是否支持虚拟化 egrep -c '(vmx|svm)' /proc/cpuinfo # 返回值大于0就支持 # 检查KVM内核模块是否加载 lsmod | grep kvm # 应该看到 kvm_intel 或 kvm_amdsudo apt update sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst virt-manager cpu-checker安装完成之后KVM的安装就结束了然后现配置一个桥接网络使用 ip a查询自己的公网IP是这哪个网卡上我这里显示 eth0之后我们使用vim编辑这个配置vim /etc/netplan/network.yaml ####然后修改我们的一个配置文件这个是一个示例 network: version: 2 renderer: networkd ethernets: eth0: dhcp4: false dhcp6: false addresses: - 服务器IP地址 match: macaddress: 'b8:ca:3a:f9:a6:95' # 重要：物理网卡不需要网关和DNS，这些要移到桥接接口 # 从eth0移除这些配置 # nameservers: # addresses: # - 223.5.5.5 # - 114.114.114.114 # routes: # - # to: 0.0.0.0/0 # via: 网关 bridges: # 创建桥接接口 br0 br0: interfaces: [eth0] # 桥接到物理网卡 dhcp4: false dhcp6: false addresses: - # 使用相同的IP nameservers: addresses: - 223.5.5.5 - 114.114.114.114 routes: - to: 0.0.0.0/0 via: 111.170.157.1 parameters: stp: false forward-delay: 0 ####退出保存之后应用更改 sudo netplan apply这样我们的br0桥接网络就完成了然后配置我们的第二个网络NAT创建 并编辑NAT 网络的 XML 配置文件sudo vim /etc/libvirt/qemu/networks/nat-network.xml ###粘贴以下配置 <network> <name>nat-network</name> <forward mode="nat"/> <bridge name="virbr1" stp="on" delay="0"/> <ip address="10.0.0.1" netmask="255.255.255.0"> <dhcp> <range start="10.0.0.2" end="10.0.0.245"/> </dhcp> </ip> </network>这个是使用的10.0.0.1/24这个网段保存并且退出之后我们需要定义并且激活设置开机自启动这个网络执行以下的命令# 定义网络 sudo virsh net-define /etc/libvirt/qemu/networks/nat-network.xml # 启动网络 sudo virsh net-start nat-network # 设置开机自启动 sudo virsh net-autostart nat-network这样我们就有了一个叫做 nat-network的网络了之后我们执行# 查看所有虚拟网络 sudo virsh net-list --all # 应该看到 nat-network 是活动的 # 查看网络详情 sudo virsh net-info nat-network就能查看我们创建的NAT网络和一个默认的NAT网络了我们需要删除这个名叫 default的网络我们执行# 停止默认网络 sudo virsh net-destroy default # 禁用自启动 sudo virsh net-autostart default --disable # 取消定义（删除）默认网络 sudo virsh net-undefine default # 再次检查网络列表 sudo virsh net-list --all这样我们就只能查询到自己创建的NAT网络了，因为我自己的/data目录是单独的一个RAID0分区所以我的ISO和虚拟机的配置文件以及虚拟机的磁盘都是放到这个目录下的如果你和我一样的话你可以使用以下的命令创建和我一样的目录mkdir /data/iso #存放系统镜像的目录 mkdir /data/kvm/config #存放虚拟机的配置文件 mkdir /data/kvm/hd #存放虚拟的硬盘文件 # 设置权限 sudo chown -R root:libvirt /data/kvm/ sudo chmod -R 775 /data/kvm/ # 查看目录 ls -la /data/kvm/然后修改libvirt 默认存储位置# 停止默认存储池 sudo virsh pool-destroy default sudo virsh pool-undefine default # 定义新的默认存储池（指向你的目录） sudo virsh pool-define-as default dir - - - - "/data/kvm/hd" sudo virsh pool-start default sudo virsh pool-autostart default # 验证 sudo virsh pool-info default这样就行了虚拟机管理脚本#!/bin/bash # 颜色定义（使用更兼容的方式） RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' MAGENTA='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' BOLD='\033[1m' RESET='\033[0m' # 配置文件 CONFIG_DIR="/data/kvm/config" DISK_DIR="/data/kvm/hd" ISO_DIR="/data/iso" SNAPSHOT_DIR="/data/kvm/snapshots" IPTABLES_RULES_FILE="/etc/iptables/rules.v4" IPTABLES_SCRIPT="/etc/network/if-pre-up.d/iptables-restore" # 创建必要的目录 mkdir -p "$CONFIG_DIR" "$DISK_DIR" "$SNAPSHOT_DIR" 2>/dev/null # 初始化NAT端口映射系统（修复版） init_nat_system() { echo -e "${YELLOW}初始化NAT端口映射系统...${RESET}" # 1. 确保iptables-persistent已安装 if ! dpkg -l | grep -q iptables-persistent 2>/dev/null; then echo -e "${YELLOW}安装iptables-persistent...${RESET}" apt-get update >/dev/null 2>&1 DEBIAN_FRONTEND=noninteractive apt-get install -y iptables-persistent >/dev/null 2>&1 fi # 2. 创建iptables规则文件 if [ ! -f "$IPTABLES_RULES_FILE" ]; then echo -e "${YELLOW}创建iptables规则文件...${RESET}" mkdir -p /etc/iptables iptables-save > "$IPTABLES_RULES_FILE" 2>/dev/null fi # 3. 创建自动恢复脚本 if [ ! -f "$IPTABLES_SCRIPT" ]; then echo -e "${YELLOW}创建iptables自动恢复脚本...${RESET}" cat > "$IPTABLES_SCRIPT" << 'EOF2' #!/bin/sh iptables-restore < /etc/iptables/rules.v4 exit 0 EOF2 chmod +x "$IPTABLES_SCRIPT" fi # 4. 确保NAT网络有转发规则 echo -e "${YELLOW}配置NAT转发规则...${RESET}" # 启用IP转发 sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-ip-forward.conf sysctl -p /etc/sysctl.d/99-ip-forward.conf >/dev/null 2>&1 # 添加基本NAT规则 if ! iptables -t nat -L POSTROUTING -n 2>/dev/null | grep -q "MASQUERADE"; then iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE fi # 修复关键：确保FORWARD规则在libvirt规则之前 # 先删除旧的FORWARD规则 iptables -D FORWARD -s 10.0.0.0/24 -j ACCEPT 2>/dev/null || true iptables -D FORWARD -d 10.0.0.0/24 -j ACCEPT 2>/dev/null || true # 获取libvirt规则位置 LIBVIRT_RULE_NUM=$(iptables -L FORWARD -n --line-numbers 2>/dev/null | grep -E "LIBVIRT_FWX|LIBVIRT_FWI|LIBVIRT_FWO" | awk '{print $1}' | head -1) if [ -n "$LIBVIRT_RULE_NUM" ]; then echo -e "${YELLOW}检测到libvirt规则，在第 $LIBVIRT_RULE_NUM 行${RESET}" # 在libvirt规则之前插入FORWARD规则 iptables -I FORWARD $LIBVIRT_RULE_NUM -s 10.0.0.0/24 -j ACCEPT iptables -I FORWARD $((LIBVIRT_RULE_NUM+1)) -d 10.0.0.0/24 -j ACCEPT else echo -e "${YELLOW}未检测到libvirt规则，直接添加FORWARD规则${RESET}" # 如果没有libvirt规则，直接添加 iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT iptables -A FORWARD -d 10.0.0.0/24 -j ACCEPT fi # 保存规则 save_iptables_rules echo -e "${GREEN}NAT端口映射系统初始化完成！${RESET}" } # 保存iptables规则 save_iptables_rules() { echo -e "${YELLOW}保存iptables规则...${RESET}" mkdir -p /etc/iptables iptables-save > "$IPTABLES_RULES_FILE" 2>/dev/null echo -e "${GREEN}规则已保存到 $IPTABLES_RULES_FILE${RESET}" } # 修复NAT端口转发问题 fix_nat_forwarding() { echo -e "${YELLOW}修复NAT端口转发问题...${RESET}" # 备份当前规则 BACKUP_FILE="/etc/iptables/rules.v4.backup.$(date +%Y%m%d_%H%M%S)" sudo cp /etc/iptables/rules.v4 "$BACKUP_FILE" 2>/dev/null echo -e "${GREEN}规则已备份到: $BACKUP_FILE${RESET}" # 重新配置FORWARD链 echo -e "${YELLOW}重新配置FORWARD链规则顺序...${RESET}" # 临时清空FORWARD链 sudo iptables -F FORWARD # 重新添加规则，确保端口转发规则在libvirt规则之前 # 1. 先添加端口转发规则 sudo iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT sudo iptables -A FORWARD -d 10.0.0.0/24 -j ACCEPT # 2. 添加libvirt规则 sudo iptables -A FORWARD -j LIBVIRT_FWX sudo iptables -A FORWARD -j LIBVIRT_FWI sudo iptables -A FORWARD -j LIBVIRT_FWO # 保存规则 save_iptables_rules echo -e "${GREEN}NAT端口转发修复完成！${RESET}" } # 显示标题 show_header() { clear echo -e "${BLUE}╔══════════════════════════════════════════════════════╗${RESET}" echo -e "${BLUE}║ ${BOLD}🐳 KVM 虚拟机管理系统 v3.1${RESET}${BLUE} ║${RESET}" echo -e "${BLUE}║ ║${RESET}" echo -e "${BLUE}║ 主机: $(hostname) ║${RESET}" echo -e "${BLUE}║ 时间: $(date '+%Y-%m-%d %H:%M:%S') ║${RESET}" echo -e "${BLUE}║ NAT网络: 10.0.0.0/24 ║${RESET}" echo -e "${BLUE}║ 桥接网络: br0 ║${RESET}" echo -e "${BLUE}║ 状态: $(systemctl is-active libvirtd) ║${RESET}" echo -e "${BLUE}╚══════════════════════════════════════════════════════╝${RESET}" echo "" } # 显示主菜单 show_main_menu() { show_header echo -e "${GREEN}┌──────────────────────────────────────┐${RESET}" echo -e "${GREEN}│ ${BOLD}主菜单${RESET}${GREEN} │${RESET}" echo -e "${GREEN}├──────────────────────────────────────┤${RESET}" echo -e "${GREEN}│ ${CYAN}1${RESET}. 查看虚拟机列表 │${RESET}" echo -e "${GREEN}│ ${CYAN}2${RESET}. 创建新虚拟机 │${RESET}" echo -e "${GREEN}│ ${CYAN}3${RESET}. 虚拟机电源管理 │${RESET}" echo -e "${GREEN}│ ${CYAN}4${RESET}. 删除虚拟机 │${RESET}" echo -e "${GREEN}│ ${CYAN}5${RESET}. NAT端口映射管理 │${RESET}" echo -e "${GREEN}│ ${CYAN}6${RESET}. 虚拟机详细信息 │${RESET}" echo -e "${GREEN}│ ${CYAN}7${RESET}. 快照管理 │${RESET}" echo -e "${GREEN}│ ${CYAN}8${RESET}. 系统状态 │${RESET}" echo -e "${GREEN}│ ${CYAN}9${RESET}. 网络配置 │${RESET}" echo -e "${GREEN}│ ${CYAN}10${RESET}. 备份/恢复虚拟机 │${RESET}" echo -e "${GREEN}│ ${CYAN}11${RESET}. 修复NAT转发 │${RESET}" echo -e "${GREEN}│ ${CYAN}0${RESET}. 退出 │${RESET}" echo -e "${GREEN}└──────────────────────────────────────┘${RESET}" echo "" read -p "$(echo -e "${YELLOW}请选择操作 [0-11]: ${RESET}")" choice } # 1. 查看虚拟机列表 list_vms() { show_header echo -e "${BOLD}📋 虚拟机列表${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}🔵 运行中的虚拟机:${RESET}" sudo virsh list echo -e "\n${YELLOW}⚪ 所有虚拟机(包括已停止):${RESET}" sudo virsh list --all echo -e "\n${YELLOW}💾 硬盘使用情况:${RESET}" echo "存储路径: ${DISK_DIR}/" sudo du -sh "$DISK_DIR" 2>/dev/null || echo "目录不存在" echo "硬盘文件:" sudo ls -lh "$DISK_DIR/" 2>/dev/null | head -10 echo -e "\n${YELLOW}🔌 网络状态:${RESET}" sudo virsh net-list --all echo -e "\n${YELLOW}🔀 NAT端口映射:${RESET}" sudo iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep -E "DNAT|dpt:" || echo "暂无端口映射" echo -e "\n${YELLOW}📊 FORWARD链规则顺序:${RESET}" sudo iptables -L FORWARD -n --line-numbers 2>/dev/null read -p "按回车键返回主菜单..." } # 2. 创建新虚拟机（交互式） create_vm_interactive() { while true; do show_header echo -e "${BOLD}🚀 创建新虚拟机${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" # 步骤1: 基本配置 echo -e "\n${YELLOW}步骤1: 基本配置${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" read -p "虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 虚拟机名称不能为空${RESET}" sleep 2 continue fi # 检查名称是否已存在 if sudo virsh list --all --name | grep -q "^${VM_NAME}$"; then echo -e "${RED}错误: 虚拟机 '${VM_NAME}' 已存在${RESET}" read -p "按回车键重新输入..." continue fi read -p "内存大小(MB) [默认: 2048]: " MEMORY MEMORY=${MEMORY:-2048} read -p "CPU核心数 [默认: 2]: " VCPU VCPU=${VCPU:-2} read -p "硬盘大小(GB) [默认: 20]: " DISK_SIZE DISK_SIZE=${DISK_SIZE:-20} # 步骤2: 选择ISO镜像 echo -e "\n${YELLOW}步骤2: 选择操作系统镜像${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" ISOS=() if [ -d "$ISO_DIR" ]; then i=0 echo -e "可用的ISO镜像:" echo -e "${CYAN}0. 手动指定ISO路径${RESET}" for iso in "$ISO_DIR"/*.iso "$ISO_DIR"/*.img; do if [ -f "$iso" ]; then i=$((i+1)) ISOS[i]="$iso" filename=$(basename "$iso") size=$(ls -lh "$iso" 2>/dev/null | awk '{print $5}') echo -e "${CYAN}$i. ${filename} (${size})${RESET}" fi done if [ $i -eq 0 ]; then echo -e "${YELLOW}未找到ISO镜像${RESET}" read -p "手动输入ISO路径: " ISO_PATH else read -p "选择ISO [0-$i]: " ISO_CHOICE if [ "$ISO_CHOICE" = "0" ]; then read -p "手动输入ISO路径: " ISO_PATH elif [ -n "${ISOS[$ISO_CHOICE]}" ]; then ISO_PATH="${ISOS[$ISO_CHOICE]}" else ISO_PATH="" fi fi else echo -e "${YELLOW}ISO目录不存在: $ISO_DIR${RESET}" read -p "输入ISO完整路径: " ISO_PATH fi if [ ! -f "$ISO_PATH" ]; then echo -e "${RED}错误: ISO文件不存在${RESET}" read -p "按回车键重新选择..." continue fi # 步骤3: 网络配置 echo -e "\n${YELLOW}步骤3: 网络配置${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" echo -e "${CYAN}1. NAT网络 (10.0.0.0/24)${RESET}" echo -e "${CYAN}2. 桥接网络 (br0)${RESET}" echo -e "${CYAN}3. 仅主机网络${RESET}" read -p "选择网络类型 [1-3]: " NET_CHOICE if [ "$NET_CHOICE" = "1" ]; then NETWORK="network=nat-network" NET_TYPE="NAT" elif [ "$NET_CHOICE" = "2" ]; then NETWORK="bridge=br0" NET_TYPE="桥接" elif [ "$NET_CHOICE" = "3" ]; then NETWORK="network=default" NET_TYPE="仅主机" else NETWORK="network=nat-network" NET_TYPE="NAT" fi # 步骤4: VNC配置 echo -e "\n${YELLOW}步骤4: VNC配置${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" # 查找可用的VNC端口 find_free_port() { for port in {5901..6000}; do if ! ss -tuln 2>/dev/null | grep -q ":$port "; then echo $port return fi done echo 5901 } FREE_PORT=$(find_free_port) read -p "VNC端口 [默认: ${FREE_PORT}]: " VNC_PORT VNC_PORT=${VNC_PORT:-$FREE_PORT} # 检查端口是否被占用 if ss -tuln 2>/dev/null | grep -q ":$VNC_PORT "; then echo -e "${RED}错误: 端口 ${VNC_PORT} 已被占用${RESET}" read -p "按回车键重新选择..." continue fi # 步骤5: 操作系统类型 echo -e "\n${YELLOW}步骤5: 选择操作系统类型${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" echo -e "常见操作系统类型:" echo -e "${CYAN}1. Ubuntu/Debian 系列${RESET}" echo -e "${CYAN}2. CentOS/RHEL/Fedora 系列${RESET}" echo -e "${CYAN}3. Windows 系列${RESET}" echo -e "${CYAN}4. 其他Linux发行版${RESET}" echo -e "${CYAN}5. 通用/自动检测${RESET}" read -p "选择操作系统系列 [1-5]: " OS_CHOICE case $OS_CHOICE in 1) echo -e "Ubuntu版本:" echo -e " ubuntu24.04 (Ubuntu 24.04)" echo -e " ubuntu22.04 (Ubuntu 22.04)" echo -e " ubuntu20.04 (Ubuntu 20.04)" echo -e " debian12 (Debian 12)" read -p "选择版本 [ubuntu24.04]: " OS_VARIANT OS_VARIANT=${OS_VARIANT:-ubuntu24.04} ;; 2) echo -e "CentOS/RHEL版本:" echo -e " centos8 (CentOS 8/RHEL 8)" echo -e " centos7 (CentOS 7/RHEL 7)" echo -e " fedora38 (Fedora 38)" read -p "选择版本 [centos8]: " OS_VARIANT OS_VARIANT=${OS_VARIANT:-centos8} ;; 3) echo -e "Windows版本:" echo -e " win10 (Windows 10)" echo -e " win11 (Windows 11)" echo -e " win2k19 (Windows Server 2019)" read -p "选择版本 [win10]: " OS_VARIANT OS_VARIANT=${OS_VARIANT:-win10} ;; 4) echo -e "其他Linux:" echo -e " generic (通用Linux)" echo -e " opensuse15.4 (openSUSE 15.4)" echo -e " alpine3.16 (Alpine 3.16)" read -p "选择版本 [generic]: " OS_VARIANT OS_VARIANT=${OS_VARIANT:-generic} ;; *) OS_VARIANT="generic" ;; esac # 步骤6: 确认配置 echo -e "\n${YELLOW}步骤6: 确认配置${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" echo -e "${BOLD}虚拟机配置汇总:${RESET}" echo -e "名称: ${VM_NAME}" echo -e "内存: ${MEMORY} MB" echo -e "CPU: ${VCPU} 核心" echo -e "硬盘: ${DISK_SIZE} GB" echo -e "ISO: $(basename "$ISO_PATH")" echo -e "网络: ${NET_TYPE}" echo -e "VNC端口: ${VNC_PORT}" echo -e "操作系统: ${OS_VARIANT}" echo -e "硬盘路径: ${DISK_DIR}/${VM_NAME}.qcow2" echo -e "\n${RED}⚠️ 警告: 创建后将无法撤销！${RESET}" read -p "确认创建? (y/n): " CONFIRM if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then break else read -p "按回车键重新配置..." fi done # 开始创建虚拟机 echo -e "\n${GREEN}⏳ 正在创建虚拟机...${RESET}" # 创建硬盘 echo -e "${YELLOW}创建硬盘...${RESET}" sudo qemu-img create -f qcow2 "${DISK_DIR}/${VM_NAME}.qcow2" "${DISK_SIZE}G" if [ $? -ne 0 ]; then echo -e "${RED}错误: 创建硬盘失败${RESET}" read -p "按回车键返回主菜单..." return fi # 创建虚拟机 echo -e "${YELLOW}创建虚拟机实例...${RESET}" # 构建virt-install命令 VIRT_INSTALL_CMD="sudo virt-install \ --name '$VM_NAME' \ --memory $MEMORY \ --vcpus $VCPU \ --disk 'path=${DISK_DIR}/${VM_NAME}.qcow2,format=qcow2,bus=virtio' \ --cdrom '$ISO_PATH' \ --network '$NETWORK,model=virtio' \ --graphics 'vnc,listen=0.0.0.0,port=$VNC_PORT' \ --noautoconsole \ --console pty,target_type=serial \ --boot cdrom,hd" # 添加操作系统参数 if [ "$OS_VARIANT" = "generic" ]; then VIRT_INSTALL_CMD="$VIRT_INSTALL_CMD --osinfo detect=on,require=off" else VIRT_INSTALL_CMD="$VIRT_INSTALL_CMD --os-variant '$OS_VARIANT'" fi # 执行命令 echo -e "${YELLOW}执行命令:${RESET}" echo -e "${CYAN}$VIRT_INSTALL_CMD${RESET}" eval $VIRT_INSTALL_CMD if [ $? -eq 0 ]; then # 备份配置文件 sudo virsh dumpxml "$VM_NAME" > "${CONFIG_DIR}/${VM_NAME}.xml" 2>/dev/null echo -e "\n${GREEN}✅ 虚拟机创建成功!${RESET}" echo -e "${BOLD}连接信息:${RESET}" echo -e "VNC连接: $(hostname -I | awk '{print $1}'):${VNC_PORT}" echo -e "配置文件: ${CONFIG_DIR}/${VM_NAME}.xml" echo -e "硬盘文件: ${DISK_DIR}/${VM_NAME}.qcow2" # 如果是NAT网络，询问是否需要端口映射 if [ "$NET_TYPE" = "NAT" ]; then echo -e "\n${YELLOW}是否要为此虚拟机配置端口映射? (y/n): ${RESET}" read setup_portmap if [[ "$setup_portmap" =~ ^[Yy]$ ]]; then setup_port_mapping "$VM_NAME" fi fi else echo -e "${RED}❌ 虚拟机创建失败${RESET}" echo -e "${YELLOW}尝试使用简化的命令创建...${RESET}" # 尝试使用简化命令 sudo virt-install \ --name "$VM_NAME" \ --memory $MEMORY \ --vcpus $VCPU \ --disk "path=${DISK_DIR}/${VM_NAME}.qcow2,format=qcow2" \ --cdrom "$ISO_PATH" \ --network "$NETWORK" \ --graphics vnc,listen=0.0.0.0,port=$VNC_PORT \ --noautoconsole \ --osinfo detect=on,require=off \ --boot cdrom,hd if [ $? -eq 0 ]; then sudo virsh dumpxml "$VM_NAME" > "${CONFIG_DIR}/${VM_NAME}.xml" 2>/dev/null echo -e "${GREEN}✅ 虚拟机创建成功!${RESET}" fi fi read -p "按回车键返回主菜单..." } # 设置端口映射（修复版） setup_port_mapping() { if [ -n "$1" ]; then VM_NAME="$1" else read -p "虚拟机名称: " VM_NAME fi if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 虚拟机名称不能为空${RESET}" return fi # 获取虚拟机IP VM_IP=$(sudo virsh net-dhcp-leases nat-network 2>/dev/null | grep -i "$VM_NAME" | awk '{print $5}' | cut -d/ -f1) if [ -z "$VM_IP" ]; then echo -e "${YELLOW}警告: 无法从DHCP获取IP，请手动输入${RESET}" read -p "虚拟机内部IP地址: " VM_IP else echo -e "${GREEN}检测到虚拟机IP: ${VM_IP}${RESET}" read -p "使用此IP? (y/n): " use_ip if [[ ! "$use_ip" =~ ^[Yy]$ ]]; then read -p "输入虚拟机内部IP地址: " VM_IP fi fi if [ -z "$VM_IP" ]; then echo -e "${RED}错误: IP地址不能为空${RESET}" return fi read -p "主机端口: " HOST_PORT if [ -z "$HOST_PORT" ]; then echo -e "${RED}错误: 主机端口不能为空${RESET}" return fi # 检查端口是否被占用 if ss -tuln 2>/dev/null | grep -q ":$HOST_PORT "; then echo -e "${RED}错误: 端口 ${HOST_PORT} 已被占用${RESET}" return fi read -p "虚拟机端口 [默认同主机端口]: " GUEST_PORT GUEST_PORT=${GUEST_PORT:-$HOST_PORT} echo -e "${CYAN}协议类型:${RESET}" echo -e "1. TCP" echo -e "2. UDP" echo -e "3. TCP+UDP" read -p "选择协议 [1-3]: " PROTO_CHOICE case $PROTO_CHOICE in 1) PROTOCOL="tcp" ;; 2) PROTOCOL="udp" ;; 3) PROTOCOL="tcp,udp" ;; *) PROTOCOL="tcp" ;; esac read -p "映射描述 [可选]: " DESC DESC=${DESC:-"Port mapping for $VM_NAME"} # 显示配置摘要 echo -e "\n${YELLOW}配置摘要:${RESET}" echo -e "虚拟机: $VM_NAME" echo -e "虚拟机IP: $VM_IP" echo -e "主机端口: $HOST_PORT" echo -e "虚拟机端口: $GUEST_PORT" echo -e "协议: $PROTOCOL" echo -e "描述: $DESC" echo -e "映射: ${HOST_PORT} -> ${VM_IP}:${GUEST_PORT}" read -p "确认添加? (y/n): " CONFIRM if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}已取消${RESET}" return fi # 添加iptables规则 echo -e "${YELLOW}添加iptables规则...${RESET}" # 修复关键：确保FORWARD规则在libvirt规则之前 # 获取libvirt规则位置 LIBVIRT_RULE_NUM=$(sudo iptables -L FORWARD -n --line-numbers 2>/dev/null | grep -E "LIBVIRT_FWX|LIBVIRT_FWI|LIBVIRT_FWO" | awk '{print $1}' | head -1) if [ -z "$LIBVIRT_RULE_NUM" ]; then LIBVIRT_RULE_NUM=1 fi if "$PROTOCOL" == "tcp,udp" ; then # 添加TCP规则 sudo iptables -t nat -A PREROUTING -p tcp --dport "$HOST_PORT" -j DNAT --to-destination "$VM_IP:$GUEST_PORT" # 在libvirt规则之前插入FORWARD规则 sudo iptables -I FORWARD $LIBVIRT_RULE_NUM -p tcp -d "$VM_IP" --dport "$GUEST_PORT" -j ACCEPT # 添加UDP规则 sudo iptables -t nat -A PREROUTING -p udp --dport "$HOST_PORT" -j DNAT --to-destination "$VM_IP:$GUEST_PORT" sudo iptables -I FORWARD $((LIBVIRT_RULE_NUM+1)) -p udp -d "$VM_IP" --dport "$GUEST_PORT" -j ACCEPT else # 添加单协议规则 sudo iptables -t nat -A PREROUTING -p "$PROTOCOL" --dport "$HOST_PORT" -j DNAT --to-destination "$VM_IP:$GUEST_PORT" sudo iptables -I FORWARD $LIBVIRT_RULE_NUM -p "$PROTOCOL" -d "$VM_IP" --dport "$GUEST_PORT" -j ACCEPT fi # 保存规则 save_iptables_rules echo -e "\n${GREEN}✅ 端口映射已添加!${RESET}" echo -e "${BOLD}访问方式:${RESET}" echo -e "外部访问: http://$(curl -s ifconfig.me 2>/dev/null || hostname -I | awk '{print $1}'):${HOST_PORT}" echo -e "内部访问: http://${VM_IP}:${GUEST_PORT}" } # 5. NAT端口映射管理 nat_port_mapping() { while true; do show_header echo -e "${BOLD}🔀 NAT端口映射管理${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" # 显示当前NAT网络虚拟机 echo -e "\n${YELLOW}NAT网络虚拟机列表:${RESET}" echo -e "IP地址自动分配范围: 10.0.0.2 - 10.0.0.245" echo "" nat_vms=0 for vm in $(sudo virsh list --all --name 2>/dev/null); do if sudo virsh dumpxml "$vm" 2>/dev/null | grep -q "nat-network"; then nat_vms=$((nat_vms+1)) VM_IP=$(sudo virsh net-dhcp-leases nat-network 2>/dev/null | grep -i "$vm" | awk '{print $5}' | cut -d/ -f1) echo -e " ${CYAN}$vm${RESET} - IP: ${VM_IP:-未知}" fi done if [ $nat_vms -eq 0 ]; then echo -e "${YELLOW}没有找到NAT网络的虚拟机${RESET}" fi echo -e "\n${YELLOW}当前端口映射规则:${RESET}" echo -e "${GREEN}────────────────────────────────────${RESET}" sudo iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep -E "DNAT|dpt:" || echo -e "暂无端口映射规则" echo -e "\n${CYAN}操作选项:${RESET}" echo -e "1. 添加端口映射" echo -e "2. 删除端口映射" echo -e "3. 查看所有映射规则" echo -e "4. 清空所有映射规则" echo -e "5. 保存规则到磁盘" echo -e "6. 恢复规则从磁盘" echo -e "7. 测试端口连接" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-7]: ${RESET}")" NAT_ACTION case $NAT_ACTION in 0) return ;; 1) setup_port_mapping ;; 2) delete_port_mapping ;; 3) show_all_port_mappings ;; 4) clear_all_port_mappings ;; 5) save_iptables_rules ;; 6) restore_iptables_rules ;; 7) test_port_connection ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键继续..." done } # 删除端口映射 delete_port_mapping() { echo -e "\n${YELLOW}当前端口映射规则:${RESET}" sudo iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep -E "DNAT|dpt:" || { echo -e "${YELLOW}暂无端口映射规则${RESET}" return } read -p "输入要删除的规则行号: " RULE_NUM if [ -z "$RULE_NUM" ]; then echo -e "${RED}错误: 行号不能为空${RESET}" return fi # 获取规则详情 RULE_INFO=$(sudo iptables -t nat -L PREROUTING -n --line-numbers 2>/dev/null | grep "^$RULE_NUM ") if [ -z "$RULE_INFO" ]; then echo -e "${RED}错误: 规则 $RULE_NUM 不存在${RESET}" return fi echo -e "\n${YELLOW}规则详情:${RESET}" echo -e "$RULE_INFO" read -p "确认删除规则 $RULE_NUM? (y/n): " CONFIRM if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}已取消${RESET}" return fi # 删除规则 sudo iptables -t nat -D PREROUTING "$RULE_NUM" # 同时删除对应的FORWARD规则 PORT=$(echo "$RULE_INFO" | grep -oP "dpt:\K[0-9]+") if [ -n "$PORT" ]; then # 删除FORWARD链中对应端口的规则 FORWARD_RULES=$(sudo iptables -L FORWARD -n --line-numbers 2>/dev/null | grep "dpt:$PORT" | awk '{print $1}' | sort -rn) for rule in $FORWARD_RULES; do sudo iptables -D FORWARD "$rule" done fi # 保存规则 save_iptables_rules echo -e "${GREEN}✅ 端口映射已删除${RESET}" } # 显示所有端口映射 show_all_port_mappings() { echo -e "\n${YELLOW}当前所有端口映射规则:${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" # PREROUTING规则 echo -e "${CYAN}PREROUTING链 (端口转发):${RESET}" sudo iptables -t nat -L PREROUTING -n -v --line-numbers 2>/dev/null | grep -E "DNAT|dpt:" || echo -e "暂无规则" echo -e "\n${CYAN}FORWARD链 (转发规则):${RESET}" sudo iptables -L FORWARD -n -v --line-numbers 2>/dev/null | grep -E "dpt:|ACCEPT.*10\." | head -20 echo -e "\n${CYAN}规则顺序检查:${RESET}" sudo iptables -L FORWARD -n --line-numbers 2>/dev/null } # 清空所有端口映射 clear_all_port_mappings() { echo -e "${RED}⚠️ ⚠️ ⚠️ 警告: 这将删除所有端口映射规则！ ⚠️ ⚠️ ⚠️ ${RESET}" read -p "确认清空所有端口映射规则? (y/n): " CONFIRM if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}已取消${RESET}" return fi echo -e "${YELLOW}正在清空所有端口映射规则...${RESET}" # 清空PREROUTING链中的所有DNAT规则 sudo iptables -t nat -F PREROUTING 2>/dev/null # 保存规则 save_iptables_rules echo -e "${GREEN}✅ 所有端口映射规则已清空${RESET}" } # 恢复iptables规则 restore_iptables_rules() { echo -e "${YELLOW}从磁盘恢复iptables规则...${RESET}" if [ -f "$IPTABLES_RULES_FILE" ]; then sudo iptables-restore < "$IPTABLES_RULES_FILE" echo -e "${GREEN}✅ 规则已恢复${RESET}" else echo -e "${RED}错误: 规则文件不存在${RESET}" fi } # 测试端口连接 test_port_connection() { echo -e "${YELLOW}测试端口连接${RESET}" read -p "虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 虚拟机名称不能为空${RESET}" return fi # 获取虚拟机IP VM_IP=$(sudo virsh net-dhcp-leases nat-network 2>/dev/null | grep -i "$VM_NAME" | awk '{print $5}' | cut -d/ -f1) if [ -z "$VM_IP" ]; then echo -e "${YELLOW}无法获取虚拟机IP，请输入: ${RESET}" read -p "虚拟机IP: " VM_IP fi read -p "测试端口: " TEST_PORT echo -e "\n${CYAN}测试1: 宿主机 -> 虚拟机${RESET}" if curl -s -o /dev/null -w "HTTP状态码: %{http_code}\n" http://$VM_IP:$TEST_PORT --connect-timeout 3; then echo -e "${GREEN}✅ 内部连接成功${RESET}" else echo -e "${RED}❌ 内部连接失败${RESET}" fi echo -e "\n${CYAN}测试2: 外部 -> 宿主机${RESET}" PUBLIC_IP=$(curl -s ifconfig.me || hostname -I | awk '{print $1}') echo -e "公网IP: $PUBLIC_IP" echo -e "测试命令: curl http://$PUBLIC_IP:$TEST_PORT" echo -e "\n${CYAN}测试3: 检查iptables规则${RESET}" echo -e "DNAT规则:" sudo iptables -t nat -L PREROUTING -n 2>/dev/null | grep "dpt:$TEST_PORT" echo -e "\nFORWARD规则:" sudo iptables -L FORWARD -n 2>/dev/null | grep "dpt:$TEST_PORT" } # 3. 虚拟机电源管理 power_management() { while true; do show_header echo -e "${BOLD}🔌 虚拟机电源管理${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}可管理的虚拟机:${RESET}" sudo virsh list --all echo -e "\n${CYAN}操作选项:${RESET}" echo -e "1. 启动虚拟机" echo -e "2. 正常关机" echo -e "3. 强制关机" echo -e "4. 重启虚拟机" echo -e "5. 挂起虚拟机" echo -e "6. 恢复虚拟机" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-6]: ${RESET}")" POWER_ACTION case $POWER_ACTION in 0) return ;; 1|2|3|4|5|6) read -p "输入虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 请输入虚拟机名称${RESET}" sleep 2 continue fi case $POWER_ACTION in 1) sudo virsh start "$VM_NAME" && echo -e "${GREEN}✅ 虚拟机已启动${RESET}" ;; 2) sudo virsh shutdown "$VM_NAME" && echo -e "${GREEN}✅ 已发送关机信号${RESET}" ;; 3) sudo virsh destroy "$VM_NAME" && echo -e "${GREEN}✅ 虚拟机已强制关闭${RESET}" ;; 4) sudo virsh reboot "$VM_NAME" && echo -e "${GREEN}✅ 已发送重启信号${RESET}" ;; 5) sudo virsh suspend "$VM_NAME" && echo -e "${GREEN}✅ 虚拟机已挂起${RESET}" ;; 6) sudo virsh resume "$VM_NAME" && echo -e "${GREEN}✅ 虚拟机已恢复${RESET}" ;; esac ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键继续..." done } # 4. 删除虚拟机 delete_vm() { show_header echo -e "${BOLD}🗑️ 删除虚拟机${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}虚拟机列表:${RESET}" sudo virsh list --all read -p "输入要删除的虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 请输入虚拟机名称${RESET}" read -p "按回车键返回主菜单..." return fi if ! sudo virsh list --all --name 2>/dev/null | grep -q "^${VM_NAME}$"; then echo -e "${RED}错误: 虚拟机 '$VM_NAME' 不存在${RESET}" read -p "按回车键返回主菜单..." return fi echo -e "\n${RED}⚠️ ⚠️ ⚠️ 警告: 此操作不可恢复！ ⚠️ ⚠️ ⚠️ ${RESET}" echo -e "将删除以下内容:" echo -e "1. 虚拟机配置" echo -e "2. 虚拟机定义" echo -e "3. 可选: 硬盘文件" echo -e "\n${CYAN}删除选项:${RESET}" echo -e "1. 只删除虚拟机定义（保留硬盘）" echo -e "2. 删除虚拟机定义和硬盘文件" echo -e "3. 取消" read -p "选择删除方式 [1-3]: " DELETE_OPTION case $DELETE_OPTION in 1) echo -e "${YELLOW}正在删除虚拟机定义...${RESET}" sudo virsh destroy "$VM_NAME" 2>/dev/null sudo virsh undefine "$VM_NAME" --keep-nvram echo -e "${GREEN}✅ 虚拟机定义已删除，硬盘文件保留${RESET}" ;; 2) echo -e "${RED}正在删除虚拟机定义和硬盘文件...${RESET}" sudo virsh destroy "$VM_NAME" 2>/dev/null sudo virsh undefine "$VM_NAME" --remove-all-storage echo -e "${GREEN}✅ 虚拟机已完全删除${RESET}" ;; 3) echo -e "${YELLOW}取消删除操作${RESET}" ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键返回主菜单..." } # 6. 虚拟机详细信息 vm_details() { show_header echo -e "${BOLD}📊 虚拟机详细信息${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" read -p "输入虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 请输入虚拟机名称${RESET}" read -p "按回车键返回主菜单..." return fi echo -e "\n${YELLOW}基本信息:${RESET}" sudo virsh dominfo "$VM_NAME" 2>/dev/null || { echo -e "${RED}错误: 虚拟机 '$VM_NAME' 不存在${RESET}" read -p "按回车键返回主菜单..." return } echo -e "\n${YELLOW}VNC信息:${RESET}" VNC_PORT=$(sudo virsh vncdisplay "$VM_NAME" 2>/dev/null | cut -d: -f2) if [ -n "$VNC_PORT" ]; then echo -e "VNC端口: $VNC_PORT" echo -e "连接地址: $(hostname -I | awk '{print $1}'):$VNC_PORT" else echo -e "VNC未启用" fi read -p "按回车键返回主菜单..." } # 7. 快照管理 snapshot_management() { show_header echo -e "${BOLD}📸 快照管理${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" read -p "输入虚拟机名称: " VM_NAME if [ -z "$VM_NAME" ]; then echo -e "${RED}错误: 请输入虚拟机名称${RESET}" read -p "按回车键返回主菜单..." return fi while true; do clear show_header echo -e "${BOLD}📸 快照管理 - $VM_NAME${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}当前快照:${RESET}" sudo virsh snapshot-list "$VM_NAME" 2>/dev/null || { echo -e "${YELLOW}暂无快照${RESET}" } echo -e "\n${CYAN}操作选项:${RESET}" echo -e "1. 创建快照" echo -e "2. 恢复快照" echo -e "3. 删除快照" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-3]: ${RESET}")" SNAP_ACTION case $SNAP_ACTION in 0) return ;; 1) read -p "快照名称: " SNAP_NAME read -p "快照描述: " SNAP_DESC sudo virsh snapshot-create-as "$VM_NAME" "$SNAP_NAME" "$SNAP_DESC" && echo -e "${GREEN}✅ 快照创建成功${RESET}" ;; 2) read -p "快照名称: " SNAP_NAME echo -e "${RED}警告: 恢复快照将丢失当前状态${RESET}" read -p "确认恢复? (y/n): " CONFIRM if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then sudo virsh snapshot-revert "$VM_NAME" "$SNAP_NAME" && echo -e "${GREEN}✅ 已恢复快照${RESET}" fi ;; 3) read -p "快照名称: " SNAP_NAME sudo virsh snapshot-delete "$VM_NAME" "$SNAP_NAME" && echo -e "${GREEN}✅ 快照已删除${RESET}" ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键继续..." done } # 8. 系统状态 system_status() { show_header echo -e "${BOLD}📈 系统状态${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}CPU使用率:${RESET}" top -bn1 | grep "Cpu(s)" | awk '{print "用户: "$2"% 系统: "$4"% 空闲: "$8"%"}' echo -e "\n${YELLOW}内存使用:${RESET}" free -h echo -e "\n${YELLOW}磁盘使用:${RESET}" df -h / echo -e "\n${YELLOW}KVM状态:${RESET}" systemctl status libvirtd --no-pager | head -20 echo -e "\n${YELLOW}虚拟机统计:${RESET}" TOTAL_VMS=$(sudo virsh list --state-running 2>/dev/null | grep -c "running") TOTAL_ALL=$(sudo virsh list --all 2>/dev/null | grep -c "-\|running") echo -e "运行中: $TOTAL_VMS 个" echo -e "总计: $TOTAL_ALL 个" echo -e "\n${YELLOW}NAT端口映射状态:${RESET}" sudo iptables -t nat -L PREROUTING -n 2>/dev/null | grep -c "DNAT" | xargs echo -e "活动映射数量: " echo -e "\n${YELLOW}FORWARD链规则顺序:${RESET}" sudo iptables -L FORWARD -n --line-numbers 2>/dev/null | head -10 read -p "按回车键返回主菜单..." } # 9. 网络配置 network_config() { while true; do show_header echo -e "${BOLD}🌐 网络配置${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${YELLOW}当前网络配置:${RESET}" echo -e "主机IP: $(hostname -I | awk '{print $1}')" echo -e "桥接接口: br0" ip addr show br0 2>/dev/null | grep inet || echo -e "br0未配置" echo -e "\n${YELLOW}虚拟网络:${RESET}" sudo virsh net-list --all echo -e "\n${CYAN}操作选项:${RESET}" echo -e "1. 查看NAT网络详情" echo -e "2. 查看DHCP租约" echo -e "3. 重启网络服务" echo -e "4. 查看防火墙规则" echo -e "5. 重启libvirt服务" echo -e "6. 检查NAT转发状态" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-6]: ${RESET}")" NET_ACTION case $NET_ACTION in 0) return ;; 1) echo -e "\n${YELLOW}NAT网络详情:${RESET}" sudo virsh net-info nat-network 2>/dev/null || echo -e "NAT网络未找到" ;; 2) echo -e "\n${YELLOW}DHCP租约:${RESET}" sudo virsh net-dhcp-leases nat-network 2>/dev/null || echo -e "无法获取DHCP租约" ;; 3) echo -e "${YELLOW}重启网络服务...${RESET}" systemctl restart systemd-networkd systemctl restart NetworkManager 2>/dev/null echo -e "${GREEN}✅ 网络服务已重启${RESET}" ;; 4) echo -e "\n${YELLOW}防火墙规则:${RESET}" sudo iptables -L -n -v ;; 5) echo -e "${YELLOW}重启libvirt服务...${RESET}" systemctl restart libvirtd echo -e "${GREEN}✅ libvirt服务已重启${RESET}" ;; 6) echo -e "\n${YELLOW}NAT转发状态检查:${RESET}" echo -e "IP转发状态: $(cat /proc/sys/net/ipv4/ip_forward)" echo -e "FORWARD链规则顺序:" sudo iptables -L FORWARD -n --line-numbers ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键继续..." done } # 10. 备份/恢复虚拟机 backup_restore() { while true; do show_header echo -e "${BOLD}💾 备份/恢复虚拟机${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "\n${CYAN}操作选项:${RESET}" echo -e "1. 备份虚拟机配置" echo -e "2. 恢复虚拟机配置" echo -e "3. 导出虚拟机" echo -e "4. 导入虚拟机" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-4]: ${RESET}")" BACKUP_ACTION case $BACKUP_ACTION in 0) return ;; 1) echo -e "\n${YELLOW}备份虚拟机配置${RESET}" read -p "虚拟机名称: " VM_NAME BACKUP_FILE="${CONFIG_DIR}/${VM_NAME}-backup-$(date +%Y%m%d-%H%M%S).xml" sudo virsh dumpxml "$VM_NAME" > "$BACKUP_FILE" 2>/dev/null && { echo -e "${GREEN}✅ 配置已备份到: $BACKUP_FILE${RESET}" } || echo -e "${RED}❌ 备份失败${RESET}" ;; 2) echo -e "\n${YELLOW}恢复虚拟机配置${RESET}" echo -e "可用备份文件:" ls -lh "${CONFIG_DIR}"/*backup*.xml 2>/dev/null | head -10 || echo -e "暂无备份" read -p "备份文件路径: " BACKUP_FILE if [ -f "$BACKUP_FILE" ]; then sudo virsh define "$BACKUP_FILE" && echo -e "${GREEN}✅ 配置已恢复${RESET}" else echo -e "${RED}错误: 文件不存在${RESET}" fi ;; *) echo -e "${YELLOW}功能开发中...${RESET}" ;; esac read -p "按回车键继续..." done } # 11. 修复NAT转发 fix_nat_forward() { show_header echo -e "${BOLD}🔧 修复NAT端口转发${RESET}" echo -e "${GREEN}══════════════════════════════════════════════════════${RESET}" echo -e "${YELLOW}当前FORWARD链规则:${RESET}" sudo iptables -L FORWARD -n --line-numbers echo -e "\n${RED}问题分析:${RESET}" echo -e "libvirt的防火墙规则可能会阻止NAT端口转发。" echo -e "需要确保端口转发规则在libvirt规则之前执行。" echo -e "" echo -e "${CYAN}修复选项:${RESET}" echo -e "1. 自动修复（推荐）" echo -e "2. 手动重新配置FORWARD链" echo -e "3. 临时禁用libvirt防火墙" echo -e "4. 查看详细诊断" echo -e "0. 返回主菜单" echo "" read -p "$(echo -e "${YELLOW}选择操作 [0-4]: ${RESET}")" FIX_ACTION case $FIX_ACTION in 0) return ;; 1) fix_nat_forwarding ;; 2) echo -e "${YELLOW}手动重新配置FORWARD链...${RESET}" sudo iptables -F FORWARD # 重新添加规则，确保顺序正确 sudo iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT sudo iptables -A FORWARD -d 10.0.0.0/24 -j ACCEPT sudo iptables -A FORWARD -j LIBVIRT_FWX sudo iptables -A FORWARD -j LIBVIRT_FWI sudo iptables -A FORWARD -j LIBVIRT_FWO save_iptables_rules echo -e "${GREEN}✅ FORWARD链已重新配置${RESET}" ;; 3) echo -e "${YELLOW}临时禁用libvirt防火墙...${RESET}" sudo iptables -F LIBVIRT_FWX sudo iptables -F LIBVIRT_FWI sudo iptables -F LIBVIRT_FWO save_iptables_rules echo -e "${GREEN}✅ libvirt防火墙已临时禁用${RESET}" echo -e "${YELLOW}注意: 重启libvirt服务后会恢复${RESET}" ;; 4) echo -e "\n${YELLOW}详细诊断信息:${RESET}" echo -e "1. 检查FORWARD链规则顺序:" sudo iptables -L FORWARD -n --line-numbers echo -e "\n2. 检查端口映射规则:" sudo iptables -t nat -L PREROUTING -n --line-numbers echo -e "\n3. 测试内部连接:" curl -s -o /dev/null -w "到10.0.0.68:5666的状态: %{http_code}\n" http://10.0.0.68:5666 --connect-timeout 3 ;; *) echo -e "${RED}无效的选择${RESET}" ;; esac read -p "按回车键继续..." } # 主程序循环 main() { # 检查是否以root运行 if [ "$EUID" -ne 0 ]; then echo -e "${RED}请使用 sudo 运行此脚本${RESET}" echo -e "使用方法: ${GREEN}sudo $0${RESET}" exit 1 fi # 检查libvirt是否安装 if ! command -v virsh &> /dev/null; then echo -e "${RED}错误: libvirt 未安装${RESET}" echo -e "请先安装: ${YELLOW}sudo apt install qemu-kvm libvirt-daemon-system${RESET}" exit 1 fi # 初始化NAT系统 init_nat_system while true; do show_main_menu case $choice in 1) list_vms ;; 2) create_vm_interactive ;; 3) power_management ;; 4) delete_vm ;; 5) nat_port_mapping ;; 6) vm_details ;; 7) snapshot_management ;; 8) system_status ;; 9) network_config ;; 10) backup_restore ;; 11) fix_nat_forward ;; 0) echo -e "\n${GREEN}👋 感谢使用 KVM 管理系统，再见！${RESET}" # 保存iptables规则 save_iptables_rules exit 0 ;; *) echo -e "${RED}无效的选择，请重新输入${RESET}" sleep 2 ;; esac done } # 运行主程序 main 一步一步都是和我一样的小伙伴可以直接拿去使用
我的博客的现状我的博客最早可以追溯到2022年我第一次开始建设自己的网站，后面在2023年经过长期的运营到达巅峰后面一落千丈甚至我的博客的数据最后的都丢了，我于是开重现复活我的博客，希望能够再次到达顶峰我现在要做的事情争取每天写一篇博文，但是都不会是低智的博客，博文品质应该是中等的才对，我的博客可能更偏向于教程类的博文和科普类的，我自己也是一名学生我也会积极的学习更好的技术给大家带来更好的文章的谢谢