PVE下虚拟机和LXC容器会有概率性的宕机(原因不详,可能是硬件问题(温度,资源,驱动),也可能系统问题),下面脚本是用于每隔15分钟检测一次虚拟机是否有心跳,如果没有心跳,就强制重启虚拟机(含LXC容器)。

  1. 脚本主体
#!/usr/bin/env bash

# 定义一个函数,用于检查并重启虚拟机或LXC容器
function check_and_restart() {
    type="${1}"     # 虚拟机或LXC容器的类型
    vm_id="${2}"    # 虚拟机或LXC容器的ID
    vm_ip="${3}"    # 虚拟机或LXC容器的IP地址

    # 使用ping命令检测虚拟机或LXC容器是否可达
    ping -c 1 "${vm_ip}" > /dev/null

    if [[ $? != 0 ]]; then
        # 记录当前时间和信息
        now=$(timedatectl status | grep 'Local time' | awk -F"Local time: " '{ print $2 }')
        echo "[${now}] [NO] id = ${vm_id}, ip = ${vm_ip} ($type)"

        if [[ "${type}" == "vm" ]]; then
            # 如果是虚拟机,尝试停止和启动虚拟机
            /usr/sbin/qm stop "${vm_id}"
            /usr/sbin/qm start "${vm_id}"
        elif [[ "${type}" == "lxc" ]]; then
            # 如果是LXC容器,尝试停止和启动LXC容器
            /usr/sbin/pct stop "${vm_id}"
            /usr/sbin/pct start "${vm_id}"
        else
            echo "Unknown VM type for id=${vm_id}"
        fi
    fi
}

# 主函数,用于循环检查虚拟机列表
function main() {
    vm_list="${1}"  # 虚拟机列表,格式为 type:id:ip

    for each in ${vm_list}; do
        type=$(echo "${each}" | awk -F: '{ print $1 }')  # 提取虚拟机或LXC容器的类型
        vm_id=$(echo "${each}" | awk -F: '{ print $2 }')  # 提取虚拟机或LXC容器的ID
        vm_ip=$(echo "${each}" | awk -F: '{ print $3 }')  # 提取虚拟机或LXC容器的IP
        check_and_restart "${type}" "${vm_id}" "${vm_ip}"  # 调用检查并重启函数
    done
}

# 需要检查的虚拟机和LXC容器列表,格式为 type:id:ip,其中type=vm表示虚拟机,type=lxc表示LXC容器
vm_list="
vm:100:192.168.50.61
vm:101:192.168.50.62
lxc:102:192.168.50.63
"

# 调用主函数并传入虚拟机和LXC容器列表
main "${vm_list}"
  1. 脚本调度
crontab -e
​
*/15 * * * * bash /root/check_and_restart.sh >> /root/log.txt

systemctl restart cron
  1. 注意事项
    因为一些虚拟机开机特别慢(以Windows代表),因此时间太短也不行,间隔尽量长一些。否则虚拟机开一半就还得stop再start,陷于永久循环。