直接提出这个问题从这里。
我正在运行 archlinux,并且我有一个经常与系统一起在其上运行的虚拟机。实际上大多数时候。
我的目标是产生以下行为:
- 关闭/断电/重新启动/停止信号发送到系统
- 除了尝试正常关闭虚拟机之外没有任何其他操作
- 如果虚拟机在 X 秒后正常关闭,则也继续关闭主机系统。
- 如果没有,则执行不同的命令
请给我一个关于该做什么的好主意,因为我什至不知道从哪里开始。我猜想有一个内核调用可以看一下。
让我知道。
我当前的代码
目前我正在使用这些脚本来正常关闭我的 kvm 虚拟机,并且它有效!但只要我的用户启动关闭或一个重启使用他的外壳。任何其他情况都行不通。
这些别名:
alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "
正在触发此功能:
#!/bin/bash
# This script checks for what is being passed to sudo.
# If the command passed is poweroff or reboot, it
# launches a custom script instead, that also looks
# fur currently running virtual machines and shuts them.
sudocheck() {
if [ $1 == "poweroff" ] || [ $1 == "reboot" ]; then
eval "sudo /home/damiano/.script/graceful $@"
else
eval "sudo $@"
fi
}
sudocheck $@
如果需要的话会启动这个脚本:
#!/bin/bash
i=0
e=0
## if virsh finds VMs running
virsh -c qemu:///system list | awk '{ print $3}' | \
if grep running > /dev/null ; then
virsh -c qemu:///system list --all | grep running | awk '{print "-c qemu:///system shutdown "$2}' | \
## shuts them dow gracefully
xargs -L1 virsh
## wait 30 seconds for them to go down
until (( i >= 30 || e == 1 )) ; do
## check every second for their status
virsh -c qemu:///system list --all | awk '{ print $3}' | \
if grep -E '(running|shutdown)' > /dev/null ; then
## keep waiting if still running
if (( i <= 30 )) ; then
sleep 1 && let i++ && echo $i
else
e=1 && notify-send 'Shutdown has been canceled' 'Please check the status of your virtual machines: seems like even though a stop signal has been sent, some are still running.' --urgency=critical
fi
else
## if no machine is running anymore, original power command can be executed
e=1 && eval $@
fi
done
fi
系统单元
我还制定了以下草案来管理虚拟机的执行:
[Unit]
Description=This service manages the execution of the %i virtual machine
Documentation=https://libvirt.org/manpages/virsh.html
[Service]
ExecStartPre=virsh -c qemu:///system
ExecStart=virsh start %i
ExecStop=virsh -c qemu:///system
ExecStop=virsh shutdown %i
TimeoutStopSec=30
KillMode=none
[Install]
WantedBy=multi-user.target
但我怎样才能告诉系统不要关闭桌面环境,保持原样直到VM已成功关闭?因为如果系统无法关闭虚拟机,我想在我的桌面环境中关闭虚拟机。我不希望计算机开始停止所有服务并保持挂起状态,直到强制关闭为止。
答案1
控制虚拟机的奇怪方式。好方法——使用systemd自动启动和停止VM。例如:
/etc/systemd/系统/[电子邮件受保护]
[Unit]
Description=QEMU virtual machine
[Service]
Environment="type=system-x86_64" "haltcmd=kill -INT $MAINPID"
EnvironmentFile=/etc/conf.d/qemu.d/%i
ExecStart=/usr/bin/qemu-${type} -name %i -nographic $args
ExecStop=/bin/sh -c ${haltcmd}
TimeoutStopSec=30
KillMode=none
[Install]
WantedBy=multi-user.target
...当然还有运行虚拟机的配置:
/etc/conf.d/qemu.d/one
type="system-x86_64"
args="-enable-kvm -m 512 -hda /dev/vg0/vm1 -net nic,macaddr=DE:AD:BE:EF:E0:00 \
-net tap,ifname=tap0 -serial telnet:localhost:7000,server,nowait,nodelay \
-monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"
haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat
# You can use other ways to shut down your VM correctly
#haltcmd="ssh powermanager@vm1 sudo poweroff"
...以及另一个虚拟机配置:
/etc/conf.d/qemu.d/two
args="-enable-kvm -m 512 -hda /srv/kvm/vm2.img -net nic,macaddr=DE:AD:BE:EF:E0:01 \
-net tap,ifname=tap1 -serial telnet:localhost:7001,server,nowait,nodelay \
-monitor telnet:localhost:7101,server,nowait,nodelay -vnc :1"
haltcmd="echo 'system_powerdown' | nc localhost 7101"
等等。感谢 ArchWiki 贡献者对于这篇文章。
答案2
当您需要单独控制每个虚拟机时,原始帖子的草稿和@Oxyd 的答案非常有用。
但是,如果需要关闭/启动所有虚拟机可以使用 libvirt 来宾,如上提到的Libvirt 文档。
- 编辑文件
/etc/conf.d/libvirt-guests
,或者/etc/sysconfig/libvirt-guests
对于 CentOS,然后ON_SHUTDOWN=shutdown
设置SHUTDOWN_TIMEOUT=0
- 我认为还需要激活该
libvirt-guests
服务,例如systemctl enable libvirt-guests
systemctl start libvirt-guests