在我的特定情况下,在安装了 Ubuntu 18.04 Bionic 和 VirtualBox-5.2.20 的新服务器后,似乎旧的自动启动客户机的方法不再可用。并不是说它有多好 - 但它起作用了。似乎没有任何干净的方法可以解决这个问题 - systemd 和 VirtualBox 如何工作一起用于智能启动、控制和关机?
答案1
与您的解决方案类似,但稍微简单一些:
- 运行并粘贴以下内容,将用户和组更新为您的用户名。
systemctl edit [email protected] --full --force
[Unit]
Description=Virtual Box Guest %I
After=network.target vboxdrv.service
Before=runlevel2.target shutdown.target
[Service]
User=USERNAME
Group=GROUPNAME
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
ExecStart=/usr/bin/VBoxManage startvm %i --type headless
ExecStop=/usr/bin/VBoxManage controlvm %i acpipowerbutton
[Install]
WantedBy=multi-user.target
重新加载 systemd:
systemctl daemon-reload
获取虚拟机列表
VBoxManage list vms
:
$ VBoxManage list vms
"Ubuntu" {1ba32309-d4c4-420a-a9c8-a38177f00bc4}
"Windows" {573df054-0e33-4389-896a-1234f10e25ad}
- 使用步骤 3 中返回的名称通过 systemd 管理虚拟机。例如,要管理“Ubuntu”虚拟机,您需要运行:
sudo systemctl start vbox@Ubuntu # Start the VM
sudo systemctl enable vbox@Ubuntu # Start the VM on boot
答案2
嗯...我想我已经找到答案了。
这是我的解决方案。当然它并不完美——我分享的部分原因是为了鼓励改进。但是——它通过 systemd 提供了自动启动、监控和关闭功能。而且我思考这至少对于这两款产品来说是朝着正确的方向发展的。
需要注意的是,以下内容假定您对 systemd 和 VirtualBox 有一定了解。它还需要在客户机上启用 ACPI 关机功能。这可能是 Windows 内置的,安装起来很简单酸度在 Linux 上,但我不假设。另外,一些客户机(Windows 版本 xxxx)可能需要进行一些“调整”以确保 ACPI 关闭立即发生 - 我在以下位置找到了一个很棒的资源https://ethertubes.com/unattended-acpi-shutdown-of-windows-server/
首先,当然需要创建一个 systemd 单元。我利用了模板。
执行提供了一个编辑器,我们将以下内容放入:[Unit] Description=VirtualBox %I Virtual Server After=network.target vboxdrv.servicesystemctl edit --full [email protected]
[Service]
Type=forking
Restart=no
TimeoutSec=5min
KillMode=process
RuntimeDirectory=vbox
RuntimeDirectoryPreserve=yes
PIDFile=/run/vbox/%I.pid
Environment='RUNDIR=/run'
Environment='PIDDIR=/vbox'
Environment='VM=%I'
ExecStart=/etc/init.d/vbox-systemd start
ExecStop=/etc/init.d/vbox-systemd stop
[Install]
WantedBy=multi-user.target
以上提供了一个基础:
- Allows for up to 5 minutes for startup/shutdown per guest
- The pid files will be stored as /run/vbox/<guest>.pid
- And the guests will be started as part of the normal boot process
这可以根据个人喜好进行调整 - 但除了服务器范围的默认值外,不要管它。稍后将对个别客人进行量身定制。现在 - 需要提供帮助脚本。我刚刚花了很长时间与 BASH 的复杂性作斗争,缺乏睡眠,并且严重缺乏使用 BASH 的积极经验。所以下面的作品有效,风格各异,我真的希望知道为什么我尝试简单的 BASH 函数会如此惨败。但我已经准备睡觉了,所以虽然这不是我最好的作品......但它确实有效!:
#! /bin/bash
# /etc/init.d/vbox-systemd: Helper script to startup & shutdown VirtualBox
# headless machines via systemd
#
# written by Daniel L. Miller <[email protected]>
# This should not be called directly (though possible with the
# proper environment variables set). This is used by the
# [email protected] template to start & stop virtual machines -
# with supervision.
# Environment variables to be defined for us by systemd unit
# RUNDIR=/run
# PIDDIR=/vbox
# VM=<vmname>
# This was setup to use environment variables - maybe support cmd line as well.
if [ ! -z "$2" ]; then
VM=$2
fi
# So...I suppose might as well set sane defaults
if [ -z "$RUNDIR" ]; then
RUNDIR='/run'
fi
if [ -z "$PIDDIR" ]; then
PIDDIR='/vbox'
fi
#
# Overprotective but trying to be good...
# These utilities should be fairly standard...
#
VB=/usr/bin/VBoxManage
GREP=/bin/grep
CUT=/usr/bin/cut
TR=/usr/bin/tr
SLEEP=/bin/sleep
WAITEXIT=300
# Make sure the utilities are available
test -x $VB || exit 3
test -x $GREP || exit 3
test -x $CUT || exit 3
test -x $TR || exit 3
# Verify the pid folder tree is defined and usable
test -d "${RUNDIR:?run directory top-level must be set}" || exit 3
test -d "$RUNDIR${PIDDIR:?pid directory must be set}" || mkdir -p "$RUNDIR$PIDDIR"
# This test is a little different - this validates the name but we don't
# care if the file exists or not. At least the moment.
test -f "$RUNDIR$PIDDIR/${VM:?Virtual Machine name must be set}.pid"
PIDFILE=$RUNDIR$PIDDIR/$VM.pid
vmactive=$($VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"')
case "${1:-''}" in
'start')
# Start the machine
$VB startvm $VM --type headless
# Give it at least a change to get started...
$SLEEP 2
# Now perform first trick and save pid
vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
if [ "x$vmactive" == "x$VM" ]; then
vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
echo $vmpid > $PIDFILE
else
exit 1;
fi
;;
'stop')
waited=0
while [ "$waited" -lt $WAITEXIT ]; do
# Test first so VB doesn't object to shutting off a non-running VM
vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
if [ "x$vmactive" != "x$VM" ]; then
echo "Proper ACPI Shutdown of $VM - or it wasn't running!"
break
fi
# Try to turn it off - repeatedly
$VB controlvm $VM acpipowerbutton
# Give it a chance to take.
$SLEEP 5
waited=$((waited+5))
done
# Time to clean up - force terminate if necessary and delete the pid file
[ "$waited" -ge $WAITEXIT ] && [ -f $PIDFILE ] && kill -s 9 $PIDFILE
[ -f $PIDFILE ] && rm $PIDFILE
;;
'status')
vmactive=`$VB list runningvms | grep $VM | cut -d ' ' -f 1 | tr -d '"'`
if [ "x$vmactive" == "x$VM" ]; then
vmpid=$($VB showvminfo $VM --log 0 | $GREP -m 1 'Process ID' | $CUT -d ':' -f4 | $TR -d ' ')
echo "$VM is running as PID $vmpid"
else
echo "$VM is not running"
fi
;;
*)
echo "Usage: vbox-systemd [start|stop|status]" >&2
exit 3;
;;
esac
所以...现在启动虚拟机所需的一切是:systemctl start vbox@<your-guest-name>
。更令人兴奋的是 -systemctl status vbox@<your-guest-name>
将提供 VM 的 systemd 状态!您甚至可以执行systemctl stop vbox@<your-guest-name>
关闭它。
要激活自动启动 - 只需运行systemctl enable vbox@<your-guest-name>
。
现在 - 如果你需要额外的控制,比如指定命令在客户机启动时,使用棘手的systemctl edit vbox@<your-guest-name>
。请注意,这次我们不使用参数--full
- 这将为此客户机创建一个覆盖文件夹,而不会复制基本单元。也许这个客户机需要来自主机的 SQL 服务:
[Unit]
After=mysql.service
Wants=mysql.service
现在,此客户端将不会启动,直到 mysql 服务器启动。或者,如果此客户端提供关键服务,您可以添加:
[Services]
Restart=yes
请记住 - 只需输入您需要添加或覆盖的 systemd 参数 - 其余的来自模板。
我希望这对其他人有帮助 —— 如果其他人可以做出贡献,请这样做!