はじめに (対象読者・この記事でわかること)

本記事は、VirtualBox を日常的に利用している開発者・インフラエンジニア、または自動テスト環境を構築したい方を対象としています。
VirtualBox 上でゲスト OS が完全に起動したことをプログラムから検知できれば、テストスクリプトの開始タイミングやデプロイ処理の自動化が格段に楽になります。本記事を読むことで、以下が実現できるようになります。

  • VBoxManage と Guest Additions を組み合わせた起動完了検知の仕組みが理解できる
  • 起動完了をフックするバッチ/シェルスクリプトを作成できる
  • 起動遅延や検知失敗時の対策・トラブルシューティングができる

このテーマは、手動で「Ready」状態を確認していた従来の作業を自動化したいというニーズから執筆しました。

前提知識

この記事をスムーズに読み進めるために、以下の知識があると便利です。

  • VirtualBox の基本操作(VM の作成・起動・停止)ができること
  • コマンドライン(Windows の PowerShell または Linux の Bash)での基本的な操作ができること
  • Guest Additions がインストールされていること(インストール手順は省略しますが、標準的な手順で問題ありません)

VirtualBoxでOS起動完了を検知する意義と概要

仮想マシン上の OS は、電源投入後に BIOS → ブートローダ → カーネル → ユーザースペースと段階的に起動します。テストや自動化のシナリオでは、「OS が完全に起動し、ネットワークやサービスが利用可能になった瞬間」を正確に把握したい場面が頻繁にあります。

VirtualBox には VBoxManage という強力なコマンドラインツールがあり、VM の状態取得やシグナル送信が可能です。さらに、Guest Additions が有効であれば、ゲスト側からホストへカスタムイベントを送ることができます。これらを組み合わせることで、次のようなフローが実現できます。

  1. VM 起動VBoxManage startvm <VM名> --type headless でバックグラウンド起動。
  2. Guest Additions の Heartbeat:ゲストが起動したら、VBoxService が定期的にホストへ「心拍」情報を送信。
  3. カスタムイベントの送出:OS の起動完了後に、VBoxControl guestproperty set "/MyApp/BootComplete" "1" などのカスタムプロパティを設定。
  4. ホスト側でポーリングVBoxManage guestproperty get <VM名> "/MyApp/BootComplete" を一定間隔で取得し、値が "1" になったら起動完了と判定。

このモデルは追加のソフトウェアやエージェントを導入せず、VirtualBox 標準機能だけで実装できる点が大きなメリットです。以下では、実際にこの仕組みを構築する手順を具体的に示します。

具体的な手順と実装例

ステップ1: 環境準備と Guest Additions の有効化

  1. VirtualBox のインストール
    最新版(6.1 以降)を公式サイトからダウンロードし、ホスト OS にインストールします。

  2. 対象 VM の作成
    任意の OS(例:Ubuntu 22.04)をインストールした仮想マシンを作成し、名前を TestVM とします。

  3. Guest Additions のインストール
    VM 起動後、メニュー > 「デバイス」 > 「Guest Additions CD イメージの挿入」を選択し、指示に従ってインストールします。インストール完了後、VM を再起動してください。

ポイント
Guest Additions が正しくインストールされていないと VBoxControl コマンドが利用できず、後述のカスタムプロパティ設定が失敗します。

ステップ2: ゲスト側スクリプトで起動完了シグナルを送る

ゲスト OS の起動が完了したことを判断するタイミングは、使う OS によって異なります。ここでは Linux 系の場合を例に、systemdmulti-user.target が起動した瞬間にシグナルを送る方法を示します。

  1. スクリプト作成
    /usr/local/bin/boot_complete.sh を作成し、実行権限を付与します。

```bash #!/bin/bash # boot_complete.sh: OS 起動完了を VirtualBox に通知する

# VBoxControl が利用可能か確認 if command -v VBoxControl >/dev/null 2>&1; then # カスタムプロパティを設定 VBoxControl guestproperty set "/MyApp/BootComplete" "1" logger -t boot_complete "VirtualBox boot complete signal sent." else logger -t boot_complete "VBoxControl not found; cannot send signal." fi ```

  1. systemd ユニットの作成
    /etc/systemd/system/boot-complete.service を作成し、multi-user.target の直後に実行されるように設定します。

```ini [Unit] Description=Notify VirtualBox that OS boot is complete After=network.target

[Service] Type=oneshot ExecStart=/usr/local/bin/boot_complete.sh

[Install] WantedBy=multi-user.target ```

  1. 有効化とテスト
    bash sudo systemctl daemon-reload sudo systemctl enable boot-complete.service

VM を再起動し、journalctl -u boot-complete.service でログが出力されれば成功です。

ステップ3: ホスト側スクリプトで起動完了をポーリング

ホスト側(例:Windows PowerShell)で、上記プロパティが "1" になるまで待機するスクリプトを作ります。

Powershell
# wait-vm-boot.ps1 param( [string]$VmName = "TestVM", [int]$TimeoutSec = 300, [int]$IntervalSec = 5 ) function Get-BootStatus { $prop = & VBoxManage guestproperty get $VmName "/MyApp/BootComplete" if ($prop -match 'Value: (\d)') { return $matches[1] } return $null } $elapsed = 0 while ($elapsed -lt $TimeoutSec) { $status = Get-BootStatus if ($status -eq "1") { Write-Host "✅ VM '$VmName' の起動が完了しました。" exit 0 } Start-Sleep -Seconds $IntervalSec $elapsed += $IntervalSec } Write-Error "⏰ タイムアウト: VM '$VmName' が $TimeoutSec 秒以内に起動完了シグナルを送信しませんでした。" exit 1

実行例:

Powershell
.\wait-vm-boot.ps1 -VmName "TestVM" -TimeoutSec 180

ステップ4: CI/CD パイプラインへの組み込み例

Jenkins のビルドステージで上記スクリプトを呼び出す例です。

Groovy
stage('Start VM') { steps { sh 'VBoxManage startvm TestVM --type headless' } } stage('Wait for Boot') { steps { bat 'powershell -ExecutionPolicy Bypass -File wait-vm-boot.ps1 -VmName TestVM -TimeoutSec 180' } } stage('Run Tests') { steps { // ここでテストスクリプトを実行 } }

このように、VM 起動 → 起動完了待ち → テスト実行という流れをコードで表現でき、手動確認の手間が排除されます。

ハマった点やエラー解決

発生した問題 原因 解決策
VBoxControl: command not found Guest Additions がインストールされていない、または PATH に登録されていない Guest Additions を再インストールし、/sbin にシンボリックリンクを作成 (sudo ln -s /usr/bin/VBoxControl /sbin/VBoxControl)
カスタムプロパティが取得できない VM が headless モードで起動され、Guest Additions のサービスが停止している VBoxManage setextradata "TestVM" "VBoxInternal/Devices/pcbios/0/Config/CBIOS" "1" で心拍機能を有効化、または VBoxManage modifyvm TestVM --vrde on で GUI 起動に切り替えて確認
タイムアウトが頻発 ゲスト側スクリプトが network.target より早く実行され、ネットワークが未確立の状態で失敗 After=network-online.target に変更し、ネットワークが確実に立ち上がってからシグナル送信させる
多重起動時にプロパティが残る 前回の実行時に BootComplete=1 が残っている VM 停止前に VBoxManage guestproperty delete "TestVM" "/MyApp/BootComplete" を実行してリセット

解決策まとめ

  1. Guest Additions のインストール状態を必ず確認
  2. systemd の依存関係 (After=) を適切に設定
  3. ホスト側でプロパティ削除を行い、状態リセット
  4. タイムアウトは実環境に合わせて調整(CPU コア数やディスク速度に依存)

まとめ

本記事では、VirtualBox の VBoxManage と Guest Additions が提供するカスタムプロパティ機能を活用し、ゲスト OS の起動完了を自動で検知する手順を詳細に解説しました。

  • 起動完了シグナルは Guest Additions の VBoxControl で設定
  • systemd ユニットで OS の安定状態(multi-user.target)をトリガー
  • ホスト側は VBoxManage guestproperty get をポーリングし、タイムアウト処理を実装
  • よくあるエラーと対策(Guest Additions 未導入、プロパティ残存、ネットワーク未完了)を網羅

この仕組みにより、テスト自動化やデプロイパイプラインで手動待機が不要となり、開発効率が大幅に向上します。次回は、複数 VM を同時監視するスケーラビリティ手法や、Windows ゲストでの同様の実装例についても取り上げる予定です。

参考資料