Macbook上でVagrant環境を作るときにイチから構築するのは面倒なので、すでにローカル環境に構築してあったVagrantゲストマシンを複製することにしました。
ただ、実際にはすんなりとは行かず、複製したVagrant box を up したときに 文字エンコーディングエラーが発生してしまったのでその対処をしたときのまとめです。
このエラーとは別に、複製したVagrant box がNICエラーでssh接続できなくなる現象も併発したので別記事にまとめています。よかったら見てみてください。
→ 複製したvagrant boxでNICエラーになりssh接続できない
このノウハウはvagrant環境を複製するときだけでなく、既存VirtualBoxの仮想マシンをVagrant化するときにもつまづくことなので、その辺を検討している方も役立つと思います。
#Vagrant boxを複製する
###実行環境
■ホストマシン
- Macbook Pro 15インチ
- Mac OS X 10.10 Yosemite
- VirtualBox 5.0.14 r105127
- Vagrant 1.7.4 + Landrush + vagrant-vbguest
- Ruby 2.0.0p481 (2014-05-08 revision 45883)
■ゲストマシン
- CentOS 6.7 64bit
- GuestAdditions 5.0.14
###実行コマンド
やりたいことは vagrant package で既存ゲストマシンをvagrant packageコマンドでパッケージ化して、vagrant box addコマンドでboxを追加すれば簡単に環境を複製できるのではないかという思惑です。
% cd /Users/[ユーザー名]/Documents/original-site.com/vagrant
% vagrant package
% mkdir /Users/[ユーザー名]/Documents/new-site.com/vagrant
% cp ./package.box /Users/[ユーザー名]/Documents/new-site.com/vagrant
% cd /Users/[ユーザー名]/Documents/new-site.com/vagrant
% vagrant box add new-site.com package.box
% vagrant box list
% vagrant init new-site.com
% vagrant up
すると、vagrant up中にrubyの文字エンコーディングエラーが発生しました。
#rubyの文字エンコーディングエラー「Encoding::UndefinedConversionErrorエラー (subprocess.rb)」
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Removing hosts
==> default: No machine id, nothing removed from /etc/hosts
==> default: Importing base box 'new-site.com'...
/opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:29:in `encode': "\xEF" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError)
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:29:in `block in initialize'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:29:in `map'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:29:in `initialize'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:22:in `new'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb:22:in `execute'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/base.rb:404:in `block in raw'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/base.rb:403:in `raw'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/base.rb:342:in `block in execute'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/retryable.rb:17:in `retryable'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/base.rb:337:in `execute'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/version_5_0.rb:209:in `import'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/import.rb:15:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/customize.rb:40:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/check_accessible.rb:18:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builder.rb:116:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/call.rb:53:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/config_validate.rb:25:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
6 require 'vagrant/util/io'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/handle_box.rb:56:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builder.rb:116:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/call.rb:53:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/check_virtualbox.rb:17:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /Users/[ユーザー名]/.vagrant.d/gems/gems/vagrant-hostsupdater-1.0.1/lib/vagrant-hostsupdater/Action/RemoveHosts.rb:23:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builder.rb:116:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/machine.rb:214:in `action_raw'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/machine.rb:191:in `block in action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/environment.rb:516:in `lock'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/machine.rb:178:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/machine.rb:178:in `action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/batch_action.rb:82:in `block (2 levels) in run'
この現象をブログなどで報告している方がいて、Vagrant環境を日本語のフォルダ配下に置いておくとこのようなEncodingエラーが起こるのでフォルダ名は英数字にすれば解消できるよと書いてありました。
しかし、今回は日本語フォルダではない環境でエラー発生したので、そう簡単には直りそうにない予感ですね。
とにかく、vagrantが使っているrubyスクリプトは日本語に対応していないようなので、日本語が使われている箇所をとにかく潰すか、もしくはrubyスクリプトを修正しなければなりませんが、普段rubyをまったく触らないのでどう対処していいか解らず2,3時間ほどしらみつぶしに色々なサイトを調べてまわりました。
いろいろ調べてみて、やっと見つけた中国サイトに修正方法が載っていたので見よう見まねで修正してみました。
###対処方法
エラーが起こっているrbファイルをvimで開いて該当行を強制的にUTF-8対応にします。
% vim /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/subprocess.rb
28行目:
前) @command = @command.map { |s| s.encode(Encoding.default_external) }
後) @command = @command.map { |s| s.force_encoding('UTF-8') }
この修正をした後に、もういちどboxファイルの追加からやり直してみます。
% vagrant destroy
% vagrant box add new-site.com package.box
% vagrant init new-site.com
% vagrant up
そうしたら、また別のRubyスクリプトで文字エンコーディングエラーが発生しました。
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Removing hosts
==> default: No machine id, nothing removed from /etc/hosts
==> default: Importing base box 'new-site.com'...
Progress: 90%/opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/version_5_0.rb:235:in `match': incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string) (Encoding::CompatibilityError)
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/version_5_0.rb:235:in `import'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/import.rb:15:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/customize.rb:40:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/action/check_accessible.rb:18:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builder.rb:116:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `block in run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/util/busy.rb:19:in `busy'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/runner.rb:66:in `run'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/call.rb:53:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/config_validate.rb:25:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/warden.rb:34:in `call'
from /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/action/builtin/handle_box.rb:56:in `call'
エラーを吐いているファイルをvimで開いて修正します。
% vim /opt/vagrant/embedded/gems/gems/vagrant-1.7.4/plugins/providers/virtualbox/driver/version_5_0.rb
234行目:
前) output = execute("list", "vms", retryable: true)
後) output = execute("list", "vms", retryable: true).force_encoding('UTF-8')
この修正をした後に、もういちどboxファイルの追加からやり直しました。
% vagrant destroy
% vagrant box add new-site.com package.box
% vagrant init new-site.com
% vagrant up
これで無事に起動できるようになりました。
とりあえず、Vagrantコマンドをたたいたときにrubyスクリプトが文字エンコーディングエラーを吐いたら、force_encoding('UTF-8') を付けて回避しましょう。
この記事を書きながらrubyのバージョンが古いことが原因なのかなとか思ったりしましたがまだ検証できていません。
ほかにも、もっといい解決方法などあれば教えて下さい。