「その他/VirtualBoxをWindowsサービス化_win7」の編集履歴(バックアップ)一覧はこちら

その他/VirtualBoxをWindowsサービス化_win7」(2018/08/17 (金) 23:45:51) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

* VirtualBoxをWindowsサービス化する #contents VirtualBoxで作成した仮想マシンをWindowsのサービスとして動作させてみた。 - 環境 -- OS: Windows 7 x64 -- PowerShell: PowerShell V3 -- VirtualBox: VirtualBox 4.3.26 - 使用したソフト -- WinSW: WinSW 1.16 ---- ** はじめに VirtualBoxをWindowsサービスとして動作させたかった。 Windowsサービスとして動作させたい要件は下記の通り。 - 要件 -- ホストOSの起動時に仮想マシンも起動すること -- ホストOSの停止時に仮想マシンも停止すること -- ホストOSのスリープから復帰しても継続して仮想マシンを使えること -- (可能な限り)他のソフトをインストールせずに使えること --- 私はソフトをインストールするという行為が好きじゃないので。レジストリが汚れるのが嫌だ。 まずはじめに、Google先生から先輩諸氏のやり方を教えてもらった。 - バッチでコマンドを叩く方法 -- [[VirtualBoxの仮想OSをバックグラウンド(画面なし)で起動する方法・Windows編>http://win.just4fun.biz/?%E4%BB%AE%E6%83%B3%E5%8C%96%E9%96%A2%E9%80%A3%E3%82%BD%E3%83%95%E3%83%88%2FVirtualBox%E3%81%AE%E4%BB%AE%E6%83%B3OS%E3%82%92%E3%83%90%E3%83%83%E3%82%AF%E3%82%B0%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%28%E7%94%BB%E9%9D%A2%E3%81%AA%E3%81%97%29%E3%81%A7%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%83%BBWindows%E7%B7%A8]] -- [[Windows起動時にVirtualBoxゲストOSを自動起動させる>http://www.hyk-home.com/blog/infra/archives/2009/12/15-094457-198.html]] - VBoxVmServiceを使う方法 -- [[VirtualBoxをWindows上のサービスとして設定していろいろ調整>http://www.civic-apps.com/2013/03/18/virtualbox-service/]] -- [[VirtualBoxをWindowsのサービスとして動かす>http://yuu.nkjm.info/diary/20110317.html]] VBoxManage.exeをコマンド実行してみたところ、ホストOSのスリープでゲストOSが落ちてしまった。 スリープが使えるのは絶対条件なので、VBoxManage.exeを使うセンはないな。 VBoxVmServiceは良さそうなんだけど、インストールしないと使えないのが嫌だ。 クリーンなソフトを使いたい。 他に方法がなければ検討することにして後回し。 いろいろ調べてみるうちに、VirtualBox.exeの引数で.vboxファイルを渡してやると仮想マシンを起動してくれることが分かった。 GUIのコンソールも一緒に起動してしまうが、この方法で起動するとホストOSのスリープ時に自動でゲストOSを一時停止し、スリープ復帰時に再開してくれるようだ。 停止は上記のVBoxManage.exeでできる。 Windowsサービスとして動かしてしまえば、GUIコンソールは裏で動いていて見えないし、要件全部クリアじゃね?ってことで、任意のプログラムをサービス化する素晴らしいソフト [[WinSW>https://github.com/kohsuke/winsw]]を使うことにした。 このソフトなら、ローカルに置いた.exeをサービス登録するだけで使える。 使い方のチュートリアルは [[winsw - 任意のプログラムをWindowsのサービスに>http://www.moongift.jp/2014/03/winsw-%E4%BB%BB%E6%84%8F%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92windows%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AB/]] を参考にした。 ** 起動・停止のスクリプト化 VirtualBox.exeは非同期に動作するプログラムのようで、コマンド実行するとすぐに制御が返ってきてしまう。 そのままではWinSWに登録できないので、起動~状態監視と、停止をスクリプトで書くことにした。 最近使い出したPowerShellで書いてみる。 *** 起動スクリプト - Start-VM.ps1 #blockquote(){{ #nowiki(){{ ################################################################################ # @file # @author leo # @brief 仮想マシンを起動する # @details # @param vmfile VMの構成ファイル (*.vbox)。パイプライン入力可。 # @param synchronousMode (オプション)同期モード。trueを指定すると同期モード。デフォルトはfalse。 # @param timeout (オプション)同期モードのときの監視を開始するまでのタイムアウト時間 [msec]。デフォルトは 60000 [msec]。 # @param monitorInterval (オプション)同期モードのときのVM起動状態を監視する間隔 [msec]。デフォルトは 1000 [msec]。 # @return なし # # @version 1.0.0 新規作成 ################################################################################ param ( [parameter(Mandatory=$true, ValueFromPipeline=$true)] [string]$vmfile, [bool]$synchronousMode=$false, [int]$timeout=60000, [int]$monitorInterval=1000 ) begin { pushd (Split-Path $MyInvocation.MyCommand.Definition -Parent) echo "[$($MyInvocation.MyCommand.Name)] [start] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" function Get-RunningVM { return (VBoxManage.exe list runningvms) -join "`n" | Select-String -Pattern '"(?<name>.*?)"\s+?{(?<uuid>.*?)}' -AllMatches | foreach { $_.Matches } | foreach { [PSCustomObject]@{ name = $_.Groups["name"].Value; uuid = $_.Groups["uuid"].value } } } } process { # 名前を特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'name="(?<name>.*)"')) { Write-Error "name not found." return -1 } $name = $matches["name"] # UUIDを特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'UUID="(?<uuid>.*)"')) { Write-Error "UUID not found." return -1 } $uuid = $matches["uuid"] # 既に起動しているかどうかのチェック if ((Get-RunningVM).uuid -contains $uuid) { Write-Error "$name {$uuid} already running." return -1 } echo "Starting ... $name {$uuid}" VirtualBox.exe "$vmfile" # 起動待ち [System.Diagnostics.Stopwatch]$timer = New-Object System.Diagnostics.Stopwatch $timer.Start() while ($synchronousMode) { sleep -Milliseconds $monitorInterval if ((Get-RunningVM).uuid -contains $uuid) { $timer.Stop() echo "$name {$uuid} started." echo " starting time = $($timer.ElapsedMilliseconds) [msec]" break } # タイムアウトの検出 if ($timeout -le $timer.ElapsedMilliseconds) { $timer.Stop() Write-Error "$name {$uuid} cannot start." Write-Error " starting time = $($timer.ElapsedMilliseconds) [msec]" return -1 } } # 監視開始 while ($synchronousMode) { sleep -Milliseconds $monitorInterval if (!((Get-RunningVM).uuid -contains $uuid)) { echo "$name {$uuid} stopped." break } } } end { echo "[$($MyInvocation.MyCommand.Name)] [end] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" popd } }} }} *** 停止スクリプト - Stop-VM.ps1 #blockquote(){{ #nowiki(){{ ################################################################################ # @file # @author leo # @brief 仮想マシンを停止する # @details # @param vmfile VMの構成ファイル (*.vbox)。パイプライン入力可。 # @return なし # # @version 1.0.3 新規作成 ################################################################################ param ( [parameter(Mandatory=$true, ValueFromPipeline=$true)] [string]$vmfile ) begin { pushd (Split-Path $MyInvocation.MyCommand.Definition -Parent) echo "[$($MyInvocation.MyCommand.Name)] [start] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" } process { # UUIDを特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'UUID="(?<uuid>.*)"')) { Write-Error "UUID not found." return -1 } $uuid = $matches["uuid"] $result = (VBoxManage.exe controlvm "$uuid" acpipowerbutton) } end { echo "[$($MyInvocation.MyCommand.Name)] [end] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" popd } }} }} ** WinSWの設定ファイル 今回は、"vm-test"とう名前の仮想マシンをサービス化してみる。 - vm-test.xml #blockquote(){{ #nowiki(){{ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <service> <id>vm-test</id> <name>vm-test</name> <description>仮想マシン</description> <startmode>Automatic</startmode> <depend></depend> <serviceaccount> <domain>.</domain> <user>username</user> <password>password</password> <allowservicelogon>true</allowservicelogon> </serviceaccount> <executable>powershell</executable> <startargument>-NoLogo</startargument> <startargument>-ExecutionPolicy</startargument> <startargument>RemoteSigned</startargument> <startargument>Start-VM.ps1</startargument> <startargument>F:\VirtualMachines\test\test.vbox</startargument> <startargument>$true</startargument> <stopexecutable>powershell</stopexecutable> <stopargument>-NoLogo</stopargument> <stopargument>-ExecutionPolicy</stopargument> <stopargument>RemoteSigned</stopargument> <stopargument>Stop-VM.ps1</stopargument> <stopargument>F:\VirtualMachines\test\test.vbox</stopargument> <logpath>log\vm</logpath> <log mode="roll-by-time"> <pattern>yyyyMMdd</pattern> </log> </service> }} }} ** サービス化 あとは、vm-test.xmlと同じディレクトリに - vm-test.exe (WinSW.exeのコピー) - Start-VM.ps1 - Stop-VM.ps1 を配置して vm-test.exe install でサービスインストール。 起動、停止、スリープからの復帰も問題なくできる。 ----
* VirtualBoxをWindowsサービス化する (Windows 7) #contents VirtualBoxで作成した仮想マシンをWindowsのサービスとして動作させてみた。 - 環境 -- OS: Windows 7 x64 -- PowerShell: PowerShell V3 -- VirtualBox: VirtualBox 4.3.26 - 使用したソフト -- WinSW: WinSW 1.16 ---- ** はじめに VirtualBoxをWindowsサービスとして動作させたかった。 Windowsサービスとして動作させたい要件は下記の通り。 - 要件 -- ホストOSの起動時に仮想マシンも起動すること -- ホストOSの停止時に仮想マシンも停止すること -- ホストOSのスリープから復帰しても継続して仮想マシンを使えること -- (可能な限り)他のソフトをインストールせずに使えること --- 私はソフトをインストールするという行為が好きじゃないので。レジストリが汚れるのが嫌だ。 まずはじめに、Google先生から先輩諸氏のやり方を教えてもらった。 - バッチでコマンドを叩く方法 -- [[VirtualBoxの仮想OSをバックグラウンド(画面なし)で起動する方法・Windows編>http://win.just4fun.biz/?%E4%BB%AE%E6%83%B3%E5%8C%96%E9%96%A2%E9%80%A3%E3%82%BD%E3%83%95%E3%83%88%2FVirtualBox%E3%81%AE%E4%BB%AE%E6%83%B3OS%E3%82%92%E3%83%90%E3%83%83%E3%82%AF%E3%82%B0%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%28%E7%94%BB%E9%9D%A2%E3%81%AA%E3%81%97%29%E3%81%A7%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%83%BBWindows%E7%B7%A8]] -- [[Windows起動時にVirtualBoxゲストOSを自動起動させる>http://www.hyk-home.com/blog/infra/archives/2009/12/15-094457-198.html]] - VBoxVmServiceを使う方法 -- [[VirtualBoxをWindows上のサービスとして設定していろいろ調整>http://www.civic-apps.com/2013/03/18/virtualbox-service/]] -- [[VirtualBoxをWindowsのサービスとして動かす>http://yuu.nkjm.info/diary/20110317.html]] VBoxManage.exeをコマンド実行してみたところ、ホストOSのスリープでゲストOSが落ちてしまった。 スリープが使えるのは絶対条件なので、VBoxManage.exeを使うセンはないな。 VBoxVmServiceは良さそうなんだけど、インストールしないと使えないのが嫌だ。 クリーンなソフトを使いたい。 他に方法がなければ検討することにして後回し。 いろいろ調べてみるうちに、VirtualBox.exeの引数で.vboxファイルを渡してやると仮想マシンを起動してくれることが分かった。 GUIのコンソールも一緒に起動してしまうが、この方法で起動するとホストOSのスリープ時に自動でゲストOSを一時停止し、スリープ復帰時に再開してくれるようだ。 停止は上記のVBoxManage.exeでできる。 Windowsサービスとして動かしてしまえば、GUIコンソールは裏で動いていて見えないし、要件全部クリアじゃね?ってことで、任意のプログラムをサービス化する素晴らしいソフト [[WinSW>https://github.com/kohsuke/winsw]]を使うことにした。 このソフトなら、ローカルに置いた.exeをサービス登録するだけで使える。 使い方のチュートリアルは [[winsw - 任意のプログラムをWindowsのサービスに>http://www.moongift.jp/2014/03/winsw-%E4%BB%BB%E6%84%8F%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92windows%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AB/]] を参考にした。 ** 起動・停止のスクリプト化 VirtualBox.exeは非同期に動作するプログラムのようで、コマンド実行するとすぐに制御が返ってきてしまう。 そのままではWinSWに登録できないので、起動~状態監視と、停止をスクリプトで書くことにした。 最近使い出したPowerShellで書いてみる。 *** 起動スクリプト - Start-VM.ps1 #blockquote(){{ #nowiki(){{ ################################################################################ # @file # @author leo # @brief 仮想マシンを起動する # @details # @param vmfile VMの構成ファイル (*.vbox)。パイプライン入力可。 # @param synchronousMode (オプション)同期モード。trueを指定すると同期モード。デフォルトはfalse。 # @param timeout (オプション)同期モードのときの監視を開始するまでのタイムアウト時間 [msec]。デフォルトは 60000 [msec]。 # @param monitorInterval (オプション)同期モードのときのVM起動状態を監視する間隔 [msec]。デフォルトは 1000 [msec]。 # @return なし # # @version 1.0.0 新規作成 ################################################################################ param ( [parameter(Mandatory=$true, ValueFromPipeline=$true)] [string]$vmfile, [bool]$synchronousMode=$false, [int]$timeout=60000, [int]$monitorInterval=1000 ) begin { pushd (Split-Path $MyInvocation.MyCommand.Definition -Parent) echo "[$($MyInvocation.MyCommand.Name)] [start] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" function Get-RunningVM { return (VBoxManage.exe list runningvms) -join "`n" | Select-String -Pattern '"(?<name>.*?)"\s+?{(?<uuid>.*?)}' -AllMatches | foreach { $_.Matches } | foreach { [PSCustomObject]@{ name = $_.Groups["name"].Value; uuid = $_.Groups["uuid"].value } } } } process { # 名前を特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'name="(?<name>.*)"')) { Write-Error "name not found." return -1 } $name = $matches["name"] # UUIDを特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'UUID="(?<uuid>.*)"')) { Write-Error "UUID not found." return -1 } $uuid = $matches["uuid"] # 既に起動しているかどうかのチェック if ((Get-RunningVM).uuid -contains $uuid) { Write-Error "$name {$uuid} already running." return -1 } echo "Starting ... $name {$uuid}" VirtualBox.exe "$vmfile" # 起動待ち [System.Diagnostics.Stopwatch]$timer = New-Object System.Diagnostics.Stopwatch $timer.Start() while ($synchronousMode) { sleep -Milliseconds $monitorInterval if ((Get-RunningVM).uuid -contains $uuid) { $timer.Stop() echo "$name {$uuid} started." echo " starting time = $($timer.ElapsedMilliseconds) [msec]" break } # タイムアウトの検出 if ($timeout -le $timer.ElapsedMilliseconds) { $timer.Stop() Write-Error "$name {$uuid} cannot start." Write-Error " starting time = $($timer.ElapsedMilliseconds) [msec]" return -1 } } # 監視開始 while ($synchronousMode) { sleep -Milliseconds $monitorInterval if (!((Get-RunningVM).uuid -contains $uuid)) { echo "$name {$uuid} stopped." break } } } end { echo "[$($MyInvocation.MyCommand.Name)] [end] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" popd } }} }} *** 停止スクリプト - Stop-VM.ps1 #blockquote(){{ #nowiki(){{ ################################################################################ # @file # @author leo # @brief 仮想マシンを停止する # @details # @param vmfile VMの構成ファイル (*.vbox)。パイプライン入力可。 # @return なし # # @version 1.0.3 新規作成 ################################################################################ param ( [parameter(Mandatory=$true, ValueFromPipeline=$true)] [string]$vmfile ) begin { pushd (Split-Path $MyInvocation.MyCommand.Definition -Parent) echo "[$($MyInvocation.MyCommand.Name)] [start] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" } process { # UUIDを特定 if (!((VBoxManage.exe showvminfo "$vmfile" --machinereadable) -join "`n" -match 'UUID="(?<uuid>.*)"')) { Write-Error "UUID not found." return -1 } $uuid = $matches["uuid"] $result = (VBoxManage.exe controlvm "$uuid" acpipowerbutton) } end { echo "[$($MyInvocation.MyCommand.Name)] [end] $(Get-Date -Format "yyyy/MM/dd HH:mm:ss")" popd } }} }} ** WinSWの設定ファイル 今回は、"vm-test"とう名前の仮想マシンをサービス化してみる。 - vm-test.xml #blockquote(){{ #nowiki(){{ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <service> <id>vm-test</id> <name>vm-test</name> <description>仮想マシン</description> <startmode>Automatic</startmode> <depend></depend> <serviceaccount> <domain>.</domain> <user>username</user> <password>password</password> <allowservicelogon>true</allowservicelogon> </serviceaccount> <executable>powershell</executable> <startargument>-NoLogo</startargument> <startargument>-ExecutionPolicy</startargument> <startargument>RemoteSigned</startargument> <startargument>Start-VM.ps1</startargument> <startargument>F:\VirtualMachines\test\test.vbox</startargument> <startargument>$true</startargument> <stopexecutable>powershell</stopexecutable> <stopargument>-NoLogo</stopargument> <stopargument>-ExecutionPolicy</stopargument> <stopargument>RemoteSigned</stopargument> <stopargument>Stop-VM.ps1</stopargument> <stopargument>F:\VirtualMachines\test\test.vbox</stopargument> <logpath>log\vm</logpath> <log mode="roll-by-time"> <pattern>yyyyMMdd</pattern> </log> </service> }} }} ** サービス化 あとは、vm-test.xmlと同じディレクトリに - vm-test.exe (WinSW.exeのコピー) - Start-VM.ps1 - Stop-VM.ps1 を配置して vm-test.exe install でサービスインストール。 起動、停止、スリープからの復帰も問題なくできる。 ----

表示オプション

横に並べて表示:
変化行の前後のみ表示: