VPCJ2: VirtualBoxをWindows10 Home 64bitにインストール

VirtualBoxのインストールは簡単にできましたが、問題はすでに作成してバックアップしてあった仮想マシンファイルを一括して取り込む方法です。結論としてはリンクしたクローンは全滅です。原因は新しいPCでのアカウント名を変えたために絶対パスが変更になってしまったためです。

前の関連記事:VPCJ2: USB3.0の外付けHDDのポリシー変更で転送速度向上?


Oracle VM VirtualBox5.0.22をインストール


VirtualBoxをWindows7 Home Premiun 64bitにインストールと同様にしました。

Downloads – Oracle VM VirtualBoxからVirtualBox-5.0.20-106931-Win.exeをダウンロードしてインストールしました。

USB2.0以上を使用するためにOracle VM VirtualBox Extension Packのインストールもしました。

これはOracle_VM_VirtualBox_Extension_Pack-5.0.20-106931をダウンロードしてVirtualBoxのメニューのファイル→環境設定→機能拡張、でこのファイルをVirtualBoxに取り込みます。

これを書いている間に5.0.20から5.0.22にアップグレードしたので5.0.22にアップグレードしました。

機能拡張のアップグレードも必要でしたがこれは指示通り進んでいくだけで完了しました。

すでにある仮想マシンを登録するコマンド


VPCJ2にWindows10をクリーンインストールで書いたようにリンクしたクローンはそれを登録しただけでは使えずリンクされたクローンも登録しないといけません。(結論としては私の場合は移動先のPCのアカウント名を変更したことでクローンした仮想マシンは起動できませんでした。linuxBeanのホストOSからWindows10のホストOSのVirtualBoxでも無理でした。)

C:\Users\pq\VirtualBox VMs
(pqはユーザー名)

バックアップしてあったこの仮想マシンフォルダを新しいWindows10の同じ場所に移動させました。

全部で171個も仮想マシンがあるのでGUIで手動で登録するのは現実的ではありません。

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" registervm vboxファイル

このコマンドで仮想マシンを登録できることがわかりました。

VBoxGuestAdditions.isoを入れっぱなしだとエラーが出て登録できない

C:\Users\pq>"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" registervm "C:\Users\pq\VirtualBox VMs\linuxBean14.04(1)\linuxBean14.04(1).vbox"
VBoxManage.exe: error: Cannot register the DVD image 'C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso' {a0f68e8f-5a35-4b3c-9012-6a2ac091e0f8} because a CD/DVD image 'C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso' with UUID {a2f3fa8d-4a6c-4fb1-8795-bcdf839aa139} already exists
VBoxManage.exe: error: Details: code E_INVALIDARG (0x80070057), component VirtualBoxWrap, interface IVirtualBox, callee IUnknown
VBoxManage.exe: error: Context: "OpenMachine(Bstr(a->argv[0]).raw(), machine.asOutParam())" at line 85 of file VBoxManageMisc.cpp
このようなエラーがで登録できない仮想マシンがありました。

virtualbox.org • View topic - E_INVALIADARG on existing VMs

仮想マシンに入れっぱなしになっていたVBoxGuestAdditions.isoが今のバージョンのものではないので中身が一致せずそれでエラーになっているようです。

ただ、linuxBean14.04をホストにしてVirtualBox5.0.22でゲストのlinuxBean14.04にVBoxGuestAdditions.isoを入れっぱなしにしてゲストをシャットダウンしても<DVDImages>は空っぽのままなのでどういう状況で<DVDImages>にisoが入ったままになるのかはわかりませんでした。

一番簡単な解決方法はlinuxBean14.04(1).vboxファイルをワードパッドで開いて<DVDImages></DVDImages>の間のに入っているものを消してしまう方法です。

これで解決できましたが、多数の仮想マシンに対してはこのようなことはやってられません。

How to remove or detach dvd from VirtualBox machine using VBoxManage command line - 1st Byte Solutions

この方法でできないかと思いましたが、これは登録してあるisoファイルを外す方法なので、登録できなくてエラーになっているものには使えなさそうです。

結局vboxファイルを直接編集する方法しか見つけられなかったのでバッチファイルで処理することにしました。

setlocal enabledelayedexpansion~endlocalの間では文字!が扱えない


<DVDImages>~</DVDImages>を空にするバッチファイルremoveDVDImages.batを作りました。

仮想マシンフォルダの親フォルダにおいて実行する想定です。
@echo off
rem このスクリプトがあるディレクトリのフルパス。
set SD=%CD%
rem vboxファイルをバックアップするディレクトリの作成
set WD=%SD%\vboxes_bk
if not exist "%WD%" (mkdir "%WD%")
rem ログファイルのフルパス。
set LOG=%WD%\log.txt
rem ログファイルに「年月日_時分秒」を挿入。
for /F "tokens=1 delims=." %%x in ('^(for /F "tokens=1,2,3 delims=:" %%p in ^('echo %DATE:/=%_%TIME: =0%'^) do @echo %%p%%q%%r^)') do @echo %%x >> "%LOG%"
setlocal enabledelayedexpansion
for /R %%f in ("*.vbox") do (
  rem <DVDImages>があるファイルのみ処理する。
  find "<DVDImages>" %%f
  if %ERRORLEVEL%==0 (
    rem 処理するファイルのフルパスをログに追記する。
    echo %%f >> "%LOG%"
    rem ファイル名の取得。
    set F_NAME=%%~nxf
    rem vboxファイルをbk拡張子をつけてバックアップディレクトリに移動させる。拡張子を変更しないとこれも処理されるので。
    move /Y "%%f" "%WD%\!F_NAME!.bk"
    rem 行を出力するフラグを立てる。
    set flg=1
    rem バックアップディレクトリに移動させたbkファイルから1行ずつ取り出す。
    for /f "usebackq delims=" %%A in ("%WD%\!F_NAME!.bk") do (
      set v="%%A"
      rem スペースを除いた行を得る。
      set w=!v: =!
      rem </DVDImages>の行以降は出力する。
      if !w!==^</DVDImages^> (set flg=1)
      rem 元のvboxファイルに出力する。
      if !flg!==1 (echo %%A>>"%%f")
      rem <DVDImages>の行より次の行は出力しない。
      if !w!==^<DVDImages^> (set flg=0)
    )
  )
)
endlocal
これでうまくいくと思ったらvboxファイルの2行目にあるxmlファイルのコメントタグの!が抜け落ちていしまいます。

<!--であるべきものが<--になってしまいます。

そのままVirtualBoxマネージャーに追加しようとするとExtra content at the end of the document.とエラーがでてきてできません。

解説しているページは見つけられませんが自分で理由を考えるにsetlocal enabledelayedexpansion~endlocalの間では!は文字として扱えないようです。

なので26行目と32行目でvboxファイルの行を取り出すときに!が消えてしまいます。

!!としてもechoでは何も出力されません。

この問題を解決する方法を思いつかなかったのでバッチファイル:JScriptを埋め込んでDOSコマンドと変数をやりとりするの方法を使ってJScriptで処理しようかと思いましたが、面倒なのでやめました。

sed for Windowsを使う


UTF-8の半角スペースには2種類あるで使ったsedのWindowsバージョンを見つけたのでこれで処理することにしました。

sed for WindowsからComplete package, except sourcesをダウンロードしてすべてデフォルト設定のままインストールしました。

"C:\Program Files (x86)\GnuWin32\bin\sed.exe"

これで実行できました。

PATH=%PATH%;C:\Program Files (x86)\GnuWin32\bin

これでコマンドウィンドウにsedへのパスが追加されるので以後そのコマンドウィンドウではsedだけで実行できます。

sedの使い方は少し勉強しないといけません。

sed コマンド | コマンドの使い方(Linux) | hydroculのメモ

sedでこういう時はどう書く? - Qiita

これらやC:\Program Files (x86)\GnuWin32\doc\sed\4.2.1\sed-4.2.1にあるヘルプsed.chmも参考にしました。

他にもGoogle検索するといろいろなやり方がでてきますが、Windows版と他のOSでは挙動が異なるのか動かない例もたくさんありなかなか苦労しました。

結局<DVDImages>~</DVDImages>を空にするのではなく、<DVDImages>のある行から</DVDImages>のある行までを削ることにしました。

vboxファイルがタグごとに改行されていることが全体になります。

<DVDImages>タグを丸ごと削ってもVirtualBoxマネージャーへの仮想マシンの追加は問題ありませんでした。

仮想マシンを起動するとvboxファイルの元の場所に<DVDImages/>が追加されていました。

まずはlinuxBean14.04(1).vboxの<DVDImages>のある行から</DVDImages>のある行までを削除してlinuxBean14.04(1)2.vboxに保存する例を作りました。
sed "/<DVDImages>/,/<\/DVDImages>/d" "linuxBean14.04(1).vbox" > "linuxBean14.04(1)2.vbox"
これはうまくいった例です。
sed '/<DVDImages>/,/<\/DVDImages>/d' "linuxBean14.04(1).vbox" > "linuxBean14.04(1)2.vbox"
sedのスクリプトのみシングルクォーテーションにすると「指定されたパスは無効です。」と言われます。

すべてをシングルクォーテーションにしてもダメなので、この場合はダブルクォーテーションしか使えないようです。

置換のみであればシングルクォーテーションでも問題ありませんでした。
sed "_<DVDImages>_,_</DVDImages>_d" "linuxBean14.04(1).vbox" > "linuxBean14.04(1)2.vbox"
区切りを_に変更して/のエスケープをとりましたがこれは「sed: -e 表現 #1, 文字数 1: 未知のコマンドです: 「_」」といわれます。

これもsedスクリプトの先頭がsが始まるときは問題がありません。
sed "/^<DVDImages>/,/<\/DVDImages>$/d" "linuxBean14.04(1).vbox" > "linuxBean14.04(1)2.vbox"
vboxファイルでは<DVDImages>と</DVDImages>が単独行にあるので他のタグを巻き込むのを防ぐため<DVDImages>が先頭にある行から</DVDImages>が最後にある行までを削除するようにしたかったのですが、これはなにもしてくれませんでした。

これはタグの前後にスペースが挿入されているせいだと思いました。
sed -e "s_<DVDImages>.*</DVDImages>_<DVDImages></DVDImages>_g" "linuxBean14.04(1).vbox" > "linuxBean14.04(1)2.vbox"
最初はこれを実行したかったのですが、sedで複数行にまたがったパターンマッチはいろいろ工夫しないといけないようなのであきらめました。

sed for Windowsを使って一括してvboxファイルから<DVDImages>タグを削除するバッチファイル

@echo off
rem sedのパスを通す。
PATH=%PATH%;C:\Program Files (x86)\GnuWin32\bin
rem このスクリプトがあるディレクトリのフルパス。
set SD=%CD%
rem ログファイルのフルパス。
set LOG=%SD%\log.txt
rem ログファイルに「年月日_時分秒」を挿入。
for /F "tokens=1 delims=." %%x in ('^(for /F "tokens=1,2,3 delims=:" %%p in ^('echo %DATE:/=%_%TIME: =0%'^) do @echo %%p%%q%%r^)') do @echo %%x >> "%LOG%"
rem テンポラリログファイルの作成。
set TMPLOG=%SD%\tmplog.txt
echo. > "%TMPLOG%"
echo 処理ファイル一覧 >> "%TMPLOG%"
set CNT=0
setlocal enabledelayedexpansion
for /R %%f in ("*.vbox") do (
  rem <DVDImages>があるファイルのみ処理する。
  find "<DVDImages>" "%%f"
  if !ERRORLEVEL!==0 (
    set /A CNT=!CNT!+1
    echo.
    echo %%~nxfから^<DVDImages^>タグを削除中。!CNT!個目。
    rem 処理するファイルのフルパスをログに追記する。
    echo %%f >> "%LOG%"
  echo %%f >> "%TMPLOG%"
    rem sed for Windowsで<DVDImages>タグを削除する。元ファイルはbkを付けて保存。
    sed -i.bk "/<DVDImages>/,/<\/DVDImages>/d" "%%f"
  )
)
if !CNT!==0 (
  echo. > "%TMPLOG%"
  echo 対象ファイルはありませんでした。>> "%TMPLOG%"
  ) else (
  echo. >> "%TMPLOG%"
  echo 合計!CNT!個 >> "%TMPLOG%"
  )
endlocal
rem sedを実行したディレクトリになぜかsed??????というファイルが残るのでそれを削除する。
if exist sed?????? (del /Q sed??????)
if exist "%TMPLOG%" (more "%TMPLOG%")
if exist "%TMPLOG%" (del /Q "%TMPLOG%")
これをremoveDVDImages.batとしてC:\Users\pq\VirtualBox VMsに保存しました(pqはユーザー名)。

実行してみると仮想マシン172個中7個が該当しました。

27行目でsedを使っています。

-iオプションでバックアップを作成していますが、sedを実行したディレクトリになぜかsed??????(?は任意の文字)というファイルが残ってしまうので39行目で削除しています。

バッチファイルで仮想マシンを一括追加する

@echo off
rem VBoxManage.exeのパスを通す。
PATH=%PATH%;C:\Program Files\Oracle\VirtualBox
set CNT=0
setlocal enabledelayedexpansion
for /R %%f in ("*.vbox") do (
    set /A CNT=!CNT!+1
    VBoxManage registervm "%%f"
)
  echo. 
  echo 合計!CNT!個の仮想マシンを追加しました。
  )
endlocal
これをこれをremoveDVDImages.batとしてC:\Users\pq\VirtualBox VMsに保存しました(pqはユーザー名)。

実行してみるとたくさんエラーがでてきましたが可能なものは追加されました。

追加できてもリンクしたクリーンはユーザー名を変えた新PCでは起動できず


結論から書くと、リンクしたクローンはVirtualBoxマネージャーに追加できても動きませんでした。


起動するとセッションを開けませんでした、と言われて起動できません。

Could not open the medium 'C:\Users\ユーザー名\VirtualBox VMs\linuxBean14.04(2)\Snapshots\{919b562a-d1ab-4929-b577-ed6eb7f2cca5}.vdi'.

VD: error VERR_PATH_NOT_FOUND opening image file 'C:\Users\ユーザー名\VirtualBox VMs\linuxBean14.04(2)\Snapshots\{919b562a-d1ab-4929-b577-ed6eb7f2cca5}.vdi' (VERR_PATH_NOT_FOUND).

詳細をみるとこのように言われているのでvdiファイルのパスが見つからないことがわかりました。

ここでようやく私は失敗したことに気が付きました。

vdiファイルへのパスがバックアップ元の絶対パスで指定されており、ユーザー名を変更したのでその絶対パスの指定自体が間違っているのです。

リンクしたクローンのvboxファイルをみてもこのvdiファイルへのパスを指定している部分はなく、リンク元のvboxファイルをみるとそこにこのvdiファイルへのパスの記載を見つけました。

そのパスを新しいPCのユーザー名に変更してみましたが今度はリンクしたクローンがVirtualBoxマネージャーにすら追加できなくなってしまいました。

がんばればなんとかなるかもしれませんが、ちょっと調べただけではわからなかったことと、いまはそこまでリンクしたクローンをバックアップから復元する必要性もないのでもうあきらめました。

反省点としては、新しいPCで使う予定の仮想マシンは「すべてのクローン」にしてバックアップをとることです。

リンクしたクローンを移動先のPCで起動するのは困難が予想されます。

新しいPCでもユーザー名を古いPCと同じにしておけばリンクしたクローンでもそのまま新しいPCに移動させれそうな気もしますが未確認です。

Windows同士ならまだしもLinuxに移動させるときユーザー名が同じでもだめのような気もします。

(2016.7.14追記。linuxBean14.06のホストの仮想マシンをWindows10Homeの仮想マシンに移動させてみましたが「リンクしたクローン」はvdiファイルのパスが認識されず、起動させることはできませんでした。)

図らずも新しいPCに移動させる仮想マシンは大幅に整理できてしまいました、、、

準仮想化インターフェースをKVMにしてゲストLinuxを機敏にする


選択肢は「デフォルト」「Legacy」「Minimal」「Hyper-V」「KVM」の5種類で、ゲストOSとしてWindowsを走らせるときはHyper-Vを、Linuxを走らせるときは「KVM」を、MacOSを走らせるときは「Minimal」を選択するように推奨されています。
VirtualBox 5.0リリース間近、RC2が登場。準仮想化でWindowsやLinuxの性能向上、USB 3.0対応など - Publickey Smart Editionβ3
VirualBox5から準仮想化という仕組みができたそうです。

バックアップから登録した仮想マシンの設定からシステム→アクセラレーションで準仮想化インターフェースをみるとLegacyになっていました。

これをKVMに変更すると確かに速くなったように思います。

参考にしたサイト


Downloads – Oracle VM VirtualBox
VirtualBoxのダウンロードサイト。

virtualbox.org • View topic - E_INVALIADARG on existing VMs
vboxの<DVDImages>タグに入っているisoファイルのバージョンを異なると仮想マシンを追加できない問題の解決法。

How to remove or detach dvd from VirtualBox machine using VBoxManage command line - 1st Byte Solutions
VBoxManageコマンドでDVDImagesをはずす例ですがうまく使えませんでした。

sed for Windows
sedのWindows版。

sed コマンド | コマンドの使い方(Linux) | hydroculのメモ
sedの使い方の解説。

sedでこういう時はどう書く? - Qiita
sedの使い方の解説。

VirtualBox 5.0リリース間近、RC2が登場。準仮想化でWindowsやLinuxの性能向上、USB 3.0対応など - Publickey Smart Editionβ3
準仮想化にすると仮想マシンの動作が速くなりました。

memo: Windows バッチファイル : テキストファイルにある文字列を置換したい
バッチファイルでの文字置換する方法。

For - DOS コマンド一覧 - Programming Field
いろいろできるけどすぐ使い方を忘れるForコマンド。
PR

0 件のコメント:

コメントを投稿