Vagrant+VirtualBoxでVMをいくつも上げてると、haltし忘れるVMが出てくるものです。(え、うっかりしすぎ?)
VMが立ち上がっている状態ではOSシャットダウンやリブートが正常終了しないため、立ち上がっているVMを調査して安全に停止するスクリプトを書きました。
#!/bin/bash
USER="XXXXXX" # VirtualBoxでVMを停止するユーザー
export PATH="${PATH:+$PATH:}/bin:/usr/bin:/usr/sbin:/sbin"
SU="su $USER -c"
CHK_CMD="VBoxManage --version"
CHK_WORD="sudo /etc/init.d/vboxdrv setup" # VBoxManageのバージョンアップが必要な場合
VMLIST_CMD="VBoxManage list runningvms"
VMDOWN_CMD="VBoxManage controlvm VMNAME savestate"
check_vms_state() {
echo "check VMs state"
$SU "$CHK_CMD" | grep "$CHK_WORD" >/dev/null 2>/dev/null
if [ $? != 0 ]; then
RUNNING_VMS=`$SU "$VMLIST_CMD" | wc -l`
if [ $RUNNING_VMS != 0 ]; then
echo "wait for VM shutdown"
sleep 5
check_vms_state
fi
fi
}
case "$1" in
start)
;;
stop)
$SU "$VMLIST_CMD" | cut -d\" -f2 | while read VM; do
echo "shutdown $VM"
$SU "${VMDOWN_CMD/VMNAME/$VM}"
done
check_vms_state
;;
status)
echo "running VMs:"
$SU "$VMLIST_CMD" | cut -d\" -f2 | while read VM; do
echo " $VM"
done
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 3
esac
exit 0
注意1
このスクリプトはVMを立ち上げるのはある一人のユーザーアカウントだけという前提です。複数のユーザーアカウントでVMを起動する可能性がある場合、イイカンジにスクリプトを修正してください。
注意2
Linux Kernelをアップデートすると、"Kernel driver not installed ..."という警告が出てVBoxManageのコマンドが受け付けられない場合があります。そのような場合、vboxdrvを使ってドライバの再セットアップが必要になりますが、CHK_WORDはその警告を検知するためのキーワードです。VBoxManageの仕様が変わったら、イイカンジにスクリプトを修正してください。
インストール
update-rc.dあたりを使い、適切なランレベルに仕込んでください。
$ sudo update-rc.d vboxshutdown defaults
$ ls -l /etc/rc*.d/*vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc0.d/K20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc1.d/K20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc2.d/S20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc3.d/S20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc4.d/S20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc5.d/S20vboxshutdown -> ../init.d/vboxshutdown
lrwxrwxrwx 1 root root 22 9月 30 08:43 /etc/rc6.d/K20vboxshutdown -> ../init.d/vboxshutdown