PVE 主机一键安全关机/重启脚本配置完整教程

📖 引言

在 Proxmox VE (PVE) 环境中,直接执行 shutdown -h nowreboot 关闭宿主机,会导致所有正在运行的虚拟机和容器被强制终止,可能造成数据丢失或文件系统损坏。本教程将指导你配置一套安全的一键关机/重启脚本,该脚本会先优雅地关闭所有运行中的 VM 和 CT,然后再关闭或重启宿主机,最大限度地保障数据完整性。

🎯 脚本功能与原理

  • 关机脚本shutdown_pve_safe.sh – 依次执行:

    1. 向所有运行中的 QEMU 虚拟机发送 qm shutdown 指令(通过 QEMU Guest Agent 或 ACPI)
    2. 向所有运行中的 LXC 容器发送 pct shutdown 指令
    3. 循环等待所有客户机完全停止
    4. 最后执行 /sbin/shutdown -h now 关闭宿主机
  • 重启脚本reboot_pve_safe.sh – 前 3 步相同,最后执行 /sbin/reboot 重启宿主机

  • 公共库lib/common.sh – 提取关闭所有客户机的公共函数 stop_all_guests(),供两个脚本复用。

🛠️ 前置准备:为虚拟机启用 QEMU Guest Agent

要确保 qm shutdown 能可靠地关闭虚拟机,必须在PVE 端虚拟机内部同时配置 QEMU Guest Agent。

1️⃣ 在各虚拟机内部安装并启动 Guest Agent

🔹 Debian / Ubuntu(包括 LXC 容器)

注意:LXC 容器无需安装 Guest Agent,PVE 直接通过容器接口发送关机信号,默认支持。但如果是 KVM 虚拟机,则需要安装。

  • 安装apt update && apt install -y qemu-guest-agent
  • 启动systemctl enable --now qemu-guest-agent

🔹 RockyLinux / CentOS / RHEL 系列

  • 安装dnf install -y qemu-guest-agent
  • 启动systemctl enable --now qemu-guest-agent

🔹 OpenWrt(KVM 虚拟机)

  • 更新源opkg update
  • 安装opkg install qemu-ga (注意包名为 qemu-ga
  • 启动/etc/init.d/qemu-ga enable && /etc/init.d/qemu-ga start
  • 验证service qemu-ga status 应显示 running

🔹 Windows 11 / Windows Server

  1. 挂载 virtio-win.iso 光盘镜像(可从 Fedora 仓库 下载)。
  2. 在设备管理器中,为 PCI 简易通讯控制器 手动更新驱动,指向 ISO 中的 vioserial 目录(对应系统架构)。
  3. 安装 Guest Agent:进入 ISO 中的 guest-agent/ 目录,双击运行 qemu-ga-x86_64.msi(64位系统)完成安装。
  4. 安装后服务会自动运行,可在任务管理器中查看 QEMU Guest Agent 进程。

🔹 iKuai 软路由

  • 官方不支持安装 Guest Agentqm shutdown 会回退到 ACPI 信号,需确保 iKuai 系统设置中已启用 ACPI 电源管理(默认多数已开启)。在 iKuai Web 界面中可查看电源管理选项。

🔹 ZimaOS

  • 无法安装 Guest Agent,且对 ACPI 支持不明确。此系统需特殊处理(见后续 “高级配置”)。

2️⃣ 在 PVE 宿主机上启用 Guest Agent 选项

对每个 KVM 虚拟机(QEMU 类型),需要在 PVE 配置中开启 Agent 通道。
可通过 Web 界面或命令行操作。

🖥️ Web 界面操作

  • 选择虚拟机 → 选项 (Options)QEMU Guest Agent → 编辑,将状态改为 已启用,保存。

⌨️ 命令行操作(推荐批量执行)

在 PVE 宿主机上执行(将 <VMID> 替换为实际 ID,如有集群需加 --node <节点名>):

1
qm set <VMID> --agent 1

例如为所有 QEMU 虚拟机启用:

1
2
3
for vmid in 100 103 104 105 106 107; do
qm set $vmid --agent 1
done

⚠️ 重要:重启虚拟机使配置生效

启用 Agent 选项后,必须重启虚拟机,新的 VirtIO 串口设备才会在系统内出现。
在 PVE 宿主机上执行:

1
qm reboot <VMID>

或通过 Web 界面重启。


3️⃣ 验证 Guest Agent 通信

在 PVE 宿主机上测试与虚拟机的 Agent 通信:

1
qm agent <VMID> ping
  • 成功:无任何输出(静默成功)。
  • 失败:会显示错误信息,如 Guest agent not running

也可用 qm agent <VMID> info 查看版本信息,若能返回 JSON 数据则通信正常。


📁 部署一键关机/重启脚本

目录结构

建议将脚本存放于用户目录下的 scripts/pv-tools/

1
2
3
4
5
/home/<user>/scripts/pv-tools/
├── shutdown_pve_safe.sh
├── reboot_pve_safe.sh
└── lib/
└── common.sh

1️⃣ 创建公共库文件 lib/common.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# 公共库文件: /home/<user>/scripts/pv-tools/lib/common.sh
# 功能:提供关闭所有虚拟机和容器的通用函数

stop_all_guests() {
echo "开始关闭所有运行中的虚拟机和容器..."

# 关闭 QEMU 虚拟机(通过 qm shutdown)
for vmid in $(qm list | awk 'NR>1 && $3=="running" {print $1}'); do
echo "正在关闭虚拟机: $vmid ..."
qm shutdown $vmid
sleep 10 # 给予响应时间
done

# 关闭 LXC 容器(通过 pct shutdown)
for ctid in $(pct list | awk 'NR>1 && $3=="running" {print $1}'); do
echo "正在关闭容器: $ctid ..."
pct shutdown $ctid
sleep 5
done

# 循环等待所有客户机完全停止
echo "等待所有虚拟机与容器彻底关闭..."
while true; do
running_vms=$(qm list | awk 'NR>1 && $3=="running" {print $1}' | wc -l)
running_cts=$(pct list | awk 'NR>1 && $3=="running" {print $1}' | wc -l)
total_running=$((running_vms + running_cts))

if [ "$total_running" -eq 0 ]; then
echo "所有虚拟机和容器已关闭。"
break
else
echo "仍有 $total_running 个虚拟机或容器在运行,等待中..."
sleep 5
fi
done
}

2️⃣ 创建关机脚本 shutdown_pve_safe.sh

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# 脚本: /home/<user>/scripts/pv-tools/shutdown_pve_safe.sh
# 功能: 安全关闭所有 VM/CT,然后关闭 PVE 宿主机

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
source "$SCRIPT_DIR/lib/common.sh"

stop_all_guests

echo "正在关闭 PVE 宿主机..."
/sbin/shutdown -h now

3️⃣ 创建重启脚本 reboot_pve_safe.sh

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# 脚本: /home/<user>/scripts/pv-tools/reboot_pve_safe.sh
# 功能: 安全关闭所有 VM/CT,然后重启 PVE 宿主机

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
source "$SCRIPT_DIR/lib/common.sh"

stop_all_guests

echo "正在重启 PVE 宿主机..."
/sbin/reboot

4️⃣ 赋予执行权限

1
2
chmod +x /home/<user>/scripts/pv-tools/*.sh
chmod +x /home/<user>/scripts/pv-tools/lib/*.sh

🧪 测试与验证

  1. 模拟测试(不执行实际关机):可以先注释掉最后的关机/重启命令,运行脚本观察是否正常关闭所有客户机。
  2. 完整测试:选择一个合适的时间,执行 sudo /home/<user>/scripts/pv-tools/shutdown_pve_safe.sh 观察宿主机是否正常关机。
  3. 查看日志:脚本会实时输出关闭进度,便于排查。

注意:所有脚本需要 root 权限 执行,建议使用 sudo


⚙️ 高级配置:处理不兼容系统的超时强制停止

对于 iKuaiZimaOS 这类无法安装 Guest Agent 的系统,qm shutdown 可能超时无响应,导致脚本卡死。建议采用以下策略:

方案一:在 PVE 虚拟机选项中设置“关机/停止超时”

  • 在虚拟机的 选项 中,找到 **关机/停止超时 (Shutdown/Stop timeout)**,设置为一个合适的秒数(如 60 秒)。当 qm shutdown 超时后,PVE 会自动执行 qm stop 强制停止。

方案二:在公共库中增加超时检测逻辑

可修改 stop_all_guests 函数,对每个虚拟机单独设置超时,超时后强制停止(需注意数据风险)。

示例改进代码(替换原有关闭虚拟机的循环):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for vmid in $(qm list | awk 'NR>1 && $3=="running" {print $1}'); do
echo "正在关闭虚拟机: $vmid ..."
qm shutdown $vmid
timeout=60
elapsed=0
while [ $elapsed -lt $timeout ]; do
if ! qm status $vmid | grep -q "running"; then
echo "虚拟机 $vmid 已关闭。"
break
fi
sleep 5
elapsed=$((elapsed + 5))
done
if qm status $vmid | grep -q "running"; then
echo "警告:虚拟机 $vmid 超时未响应,执行强制停止 (qm stop)"
qm stop $vmid
fi
done

可根据虚拟机 ID 或系统类型定制超时时间(例如为 ZimaOS 设置更短超时)。


❓ 常见问题与排查

Q1:qm set <VMID> --agent 1 报错 “Configuration file does not exist”

  • 原因:集群模式下配置文件存放在 /etc/pve/nodes/<节点名>/qemu-server/。尝试加上 --node <节点名> 参数,或直接编辑配置文件添加 agent: 1 行。

Q2:在 OpenWrt 中 qemu-ga 启动失败,提示 shift: shift count out of range

  • 这是脚本警告,不影响实际功能。安装后仍可启动服务,请直接执行 /etc/init.d/qemu-ga start

Q3:虚拟机内部已安装 Guest Agent,PVE 端已启用,但 qm agent ping 报错

  • 检查虚拟机是否已重启(必须重启)。
  • 检查 /dev/virtio-ports/ 是否存在设备节点,若不存在则说明串口通道未创建,需重新执行 qm set --agent 1 并重启。
  • 检查虚拟机内服务是否正在运行:systemctl status qemu-guest-agent(Linux)或任务管理器(Windows)。

Q4:LXC 容器需要安装 Guest Agent 吗?

  • 不需要pct shutdown 直接通过容器接口通信,默认支持优雅关机。

Q5:脚本执行时卡在等待 ZimaOS 关闭

  • 参考“高级配置”设置超时强制停止,或单独为该虚拟机设置超时时间。

📌 总结

通过以上步骤,你可以在 PVE 宿主机上部署一套完整的安全关机/重启脚本。核心要点:

  • 为可支持的虚拟机安装并启用 QEMU Guest Agent
  • 在 PVE 端为每个虚拟机开启 Agent 选项
  • 复用公共函数,避免重复代码
  • 对不兼容系统设置超时强制停止,保障脚本流畅执行

现在,你可以放心地执行 ./shutdown_pve_safe.sh./reboot_pve_safe.sh 来安全地管理你的 PVE 主机了。


📌 脚本存放路径/home/<user>/scripts/pv-tools/
📌 执行权限:所有 .sh 文件需 chmod +x
📌 运行方式sudo /home/<user>/scripts/pv-tools/shutdown_pve_safe.sh

如果在实际使用中遇到问题,欢迎查阅 PVE 官方文档或社区支持。Happy virtualizing! 🚀