てきとうなメモ

本の感想とか技術メモとか

Vagrant1.3.3でprivate_networkを利用するときにdyldのエラーになる問題

Mac OS X上でvagrantfileにprivate_networkの設定をした状態で

$ vagrant up

を実行すると

There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["hostonlyif", "ipconfig", "dyld: DYLD_ environment variables being ignored because main executable (/Applications/VirtualBox.app/Contents/MacOS/VBoxNetAdp", 
"--ip", "192.168.33.1", "--netmask", "255.255.255.0"]

Stderr: VBoxManage: error: The host network interface with the given name could not be found
VBoxManage: error: Details: code NS_ERROR_INVALID_ARG (0x80070057), component Host, interface IHost, callee nsISupports
VBoxManage: error: Context: "FindHostNetworkInterfaceByName(name.raw(), hif.asOutParam())" at line 220 of file VBoxManageHostonly.cpp
VBoxManage: error: Could not find interface 'dyld: DYLD_ environment variables being ignored because main executable (/Applications/VirtualBox.app/Contents/MacOS/VBoxNetAdp'

みたいなエラーになる。

このエラーの以下の部分は、コマンド列が実行されたことを意味する。

Command: ["hostonlyif", "ipconfig", "dyld: DYLD_ environment variables being ignored because main executable (/Applications/VirtualBox.app/Contents/MacOS/VBoxNetAdp", 
"--ip", "192.168.33.1", "--netmask", "255.255.255.0"]

hostonlyifはVirtualBoxCUIツールVBoxManageのサブコマンドで、VBoxManage hostonlyif ipconfigは本来

VBoxManage hostonlyif ipconfig interface_name --ip ip --netmask netmask

という構文になるべきである。しかし、今回はinterface_nameの部分にインターフェース名ではなく警告メッセージが入ってしまっているように見える。

interface_nameはVBoxManage hostonlyif ipconfigを行う前のVBoxManage hostonlyif createの実行結果の標準出力から取得している。しかし、VBoxManageはインターフェース名が表示されるべきところに警告メッセージを入れてしまっているようだ。これはVirtualBox側のバグっぽいので修正するのが難しそう。VirtualBoxが直せなくてもそもそも警告を出さなくすればいい。

この警告は内容を読むとDYLD_*環境変数が設定されているが無視すると書かれてある。Vagrantは実行時にDYLD_LIBRARY_PATH環境変数をVAGRANT_ORIGINAL_DYLD_LIBRARY_PATH環境変数に保存し、DYLD_LIBRARY_PATHにはVagrant同梱のライブラリを指すようにする。で、VBoxManageのようなサブプロセスを実行する時にVAGRANT_ORIGINAL_DYLD_LIBRARY_PATH環境変数をDYLD_LIBRARY_PATH環境変数に戻して実行する。

こう説明するとうまく行きそうな気がする。しかし、vagrantコマンドのコードを見ると、DYLD_LIBRARY_PATHが設定されていない場合、VAGRANT_ORIGINAL_DYLD_LIBRARY_PATHは空文字に設定されてしまう。そのため、サブプロセスを実行する時にDYLD_LIBRARY_PATHは空文字に設定されてしまう。さらに、DYLD_*を無視するという警告はDYLD_LIBRARY_PATHが空文字であっても発生してしまう。

そこで、lib/vagrant/util/subprocess.rbの

  process.environment["DYLD_LIBRARY_PATH"] =
    ENV["VAGRANT_ORIGINAL_DYLD_LIBRARY_PATH"] 

となっている部分を

  if ENV["VAGRANT_ORIGINAL_DYLD_LIBRARY_PATH"] && !ENV["VAGRANT_ORIGINAL_DYLD_LIBRARY_PATH"].to_s.empty?
    process.environment["DYLD_LIBRARY_PATH"] =
      ENV["VAGRANT_ORIGINAL_DYLD_LIBRARY_PATH"] 
  end 

とすると、空文字の場合は設定しないようになるので、問題は発生しなくなる。