动机
本人在一台家用电脑中安装了 PVE 虚拟机管理系统,并通过 Parsec 和相关软件远程连接到虚拟机上进行操作。每次想要关闭虚拟机的时候,需要额外去 PVE 后台关机,或者手动按下物理机的关机按键。这个操作让我觉得非常麻烦,遂考虑是不是有办法可以让 PVE 在监测到没有任何虚拟机运行的N分钟后自动关闭。想到写一个Shell脚本去完成这个事情比较简单,所以就把方案记录在这里。
实现
1. 创建脚本
将下面的脚本保存到/usr/local/bin/check_vms.sh
,其中,600
表示超时时间为10分钟,可自由修改。
# 路径和文件名用于记录上次检查的时间
#!/bin/bash
# 日志文件路径
LOG_FILE="/var/log/vm_check.log"
# 时间戳文件路径
TIMESTAMP_FILE="/var/log/last_no_vm_timestamp"
# 记录日志函数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
}
# 检查正在运行的虚拟机数量
running_vms=$(qm list | grep running | wc -l)
# 如果没有正在运行的虚拟机,记录时间戳到文件
if [ "$running_vms" -eq 0 ]; then
if [ ! -f "$TIMESTAMP_FILE" ]; then
date '+%s' > "$TIMESTAMP_FILE"
log "No running VMs found. Timestamp recorded."
else
start_time=$(cat "$TIMESTAMP_FILE")
current_time=$(date '+%s')
elapsed_time=$((current_time - start_time))
if [ "$elapsed_time" -ge 600 ]; then
log "No running VMs for 10 minutes. Shutting down PVE."
/sbin/shutdown -h now
else
log "No running VMs for $elapsed_time seconds."
fi
fi
else
log "Running VMs found: $running_vms"
rm -f "$TIMESTAMP_FILE"
fi
2. 确保脚本具有执行权限
chmod +x /usr/local/bin/check_vms.sh
3. 创建Crontab任务
通过下面命令打开 Crontab 的编辑器
crontab -e
在编辑器内添加下面的文本,实现定时运行Shell脚本。其中,5
表示每5分钟运行一次,可自由修改。
*/5 * * * * sudo bash /usr/local/bin/check_vms.sh
务必注意,这里必须要用Sudo权限运行,否则
qm list
命令没有任何返回
题外话
Q1:如何用Systemd实现定时运行
1. 创建脚本和赋予权限
这部分和上面的1、2一样,就省略了。
2. 创建Systemd服务文件
服务文件保存到下面位置: /etc/systemd/system/check_vms.service
[Unit]
Description=Check if there are running VMs
[Service]
Type=oneshot
ExecStart=/usr/local/bin/check_vms.sh
3. 创建Systemd定时器文件
定时器文件保存到下面位置:/etc/systemd/system/check_vms.timer
[Unit]
Description=Run check_vms service every 5 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.target
4. 启用Systemd服务
运行以下命令启用和启动定时器:
systemctl daemon-reload
systemctl enable check_vms.timer
systemctl start check_vms.timer
Q2: Crontab 和 Systemd 的区别是什么
crontab 的优势在于其简单易用,语法和使用方式都非常直观,特别适合设置简单的周期性任务。它非常轻量,不需要额外的配置文件和目录,且可以跨大多数类 Unix 操作系统使用。添加和修改 crontab 任务非常快捷,只需编辑 crontab 文件即可生效,无需重载或重启服务。
相比之下,systemd service 提供了更强的控制力,允许更精细地管理服务的启动、停止、重启和依赖关系。它具有更好的状态管理能力,可以查看服务的状态、日志和运行时间等详细信息。systemd 定时器可以精确到秒级别,并设置更复杂的触发条件,而且与系统其他部分集成得更好,能够高效管理系统资源。对于需要更复杂任务调度、更高精度控制和服务依赖管理的情况,systemd 是更好的选择。