Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running `grunt` on VM Shared Directory

Using Vagrant with a Windows host and Linux guest, grunt returned the following error when trying to run a job.

As I understand, this file path exceeds the 255 character limit of Windows when on a host-guest shared directory.

npm ERR! Error: EPERM, open '/u01/aa/bb/build/share/app-core/app-
ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-
wrapper/node_modules/download/node_modules/request/node_modules/form-
data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-
and-strings.js'

I could develop on a non-shared directory on my guest VM, but I'd prefer to use a shared directory since I use an IDE on the host.

How can I fix this issue so that I can run grunt on the shared directory?

like image 454
Kevin Meredith Avatar asked Apr 18 '14 17:04

Kevin Meredith


3 Answers

I experienced a similar issue while running yeoman with angular-generator. The solution I found right now is a little trick leveraging the way npm handles it's dependencies and folder structure.

Please consider that the problem you are experiencing is probably only affecting a few files (and probably only the imagemin module).

For Yeoman my solution was to first generate, skipping the automatically started installation:

yo angular appname --skip-install

Starting bower installation manually:

bower install

Starting from here it should be interesting to you: Install "request" npm module as first level module (instead of a depencdency deeply resolved inside imagemin later):

npm install request --save-dev

So if you now run the regular npm install to fetch the remaining modules, the already existing request module is used.

npm install --no-bin-links

Please note that using --no-bin-links is also a good idea if you don't want to run VirtualBox as an Administrator.

So, to answer your question. Running grunt should work if you correctly setup your packages and call npm install before. The module "request" is an arbitrary module that prevents the big path of the test-delayed-streams-and-buffers-and-strings.js file.

like image 51
Tarnschaf Avatar answered Nov 04 '22 16:11

Tarnschaf


If you are using the default vboxsf synced folder type, you may consider using the new rsync based synced folder to work around the issue.

rsync type will monitor the folders between host and guest, copy files directories to keep them in sync.

The difference between default vboxsf and rsync is that the latter will cause the guest Linux to run the application (grunt in your case) from its native file system (e.g. ext4) instead of vboxsf (provided by VirtualBox Guest Additions, after all the files are on Windows).

rsync synced folder basically make use of rsync CLI utility to copy / sync files and directories between hosts. So there are 2 copies of everything. When you run your grunt against the file system within the guest, it is native Linux file system and should not be affected by long path (but ext4 does have a max filename length of 255 bytes).

By default, Vagrant only syncs the folders on vagrant up or vagrant reload. But you can run vagrant rsync to manually force sync or vagrant rsync-auto to monitor changes and sync in real time.

Reference: http://docs.vagrantup.com/v2/synced-folders/rsync.html

You can set synced folder type to rsync in your Vagrantfile below

Vagrant.configure("2") do |config|
  config.vm.synced_folder ".", "/vagrant", type: "rsync",
    rsync__exclude: ".git/"
end

Update

Tested creating the directory tree structure and a file, no problem opening it from a Linux perspective, the file system is ext4. I suspect this is a problem with npm.

terry@arch:/$ uname -a
Linux arch.apac.lab 3.14.1-1-ARCH #1 SMP PREEMPT Mon Apr 14 20:40:47 CEST 2014 x86_64 GNU/Linux
terry@arch:/$ cat /u01/aa/bb/build/share/app-core/app-ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-wrapper/node_modules/download/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js
test

Update - rsync synced folder test

I did the previous test on a physical Linux installation. The following is on a quick test on Mac, guest is the same as above.

rsync synced folder configuration

config.vm.synced_folder ".", "/u01/aa/bb/build/share/app-core/app-ui/           node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-   wrapper/node_modules/download/node_modules/request/node_modules/form-data/        node_modules/combined-stream/test/integration", type: "rsync 

NOTE: I chown -R vagrant:vagrant /u01/ recursively beforehand to avoid permission issues when syncing.

sync on vagrant up

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default: Warning: Connection timeout. Retrying...
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Rsyncing folder: /ops/arch64/ => /u01/aa/bb/build/share/app-core/app-ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-wrapper/node_modules/download/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration
==> default: Mounting shared folders...
    default: /vagrant => /ops/arch64
==> default: VM already provisioned. Run `vagrant provision` or use `--provision` to force it

$ vagrant ssh
Last login: Sun Apr 27 10:36:10 2014 from 10.0.2.2
vagrant@archlinux:~$ cd /u01/aa/bb/build/share/app-core/app-ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-wrapper/node_modules/download/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration
vagrant@archlinux:/u01/aa/bb/build/share/app-core/app-ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-wrapper/node_modules/download/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration$ ls -l
total 12
-rw-r----- 1 vagrant vagrant   14 Apr 27 10:35 test-delayed-streams-and-buffers-and-strings.js
-rw-r----- 1 vagrant vagrant 5018 Apr 27 10:22 Vagrantfile
vagrant@archlinux:/u01/aa/bb/build/share/app-core/app-ui/node_modules/grunt-contrib-imagemin/node_modules/pngquant-bin/node_modules/bin-wrapper/node_modules/download/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration$ cat test-delayed-streams-and-buffers-and-strings.js
stackoverflow

Result is the same. As mentioned earlier, I suspect that this may be a npm issue.

like image 33
Terry Wang Avatar answered Nov 04 '22 15:11

Terry Wang


For an actual solution to this, check out this comment, or continue reading here:

config.vm.provider "virtualbox" do |v|
    v.customize ["sharedfolder", "add", :id, "--name", "www", "--hostpath", (("//?/" + File.dirname(__FILE__) + "/www").gsub("/","\\"))]
end

config.vm.provision :shell, inline: "mkdir /home/vagrant/www"
config.vm.provision :shell, inline: "mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` www /home/vagrant/www", run: "always"

In the code above, I am appending \\?\ to the current directory absolute path. This will actually force the Windows API to allow an increase in the MAX_PATH variable (normally capped at 260). Read more about max path. This is happening during the sharedfolder creation which is intentionally handled by VBoxManage and not Vagrant's "synced_folder" method. The last bit is pretty self-explanatory; we create the new shared folder and then make sure it's mounted each time the machine is accessed or touched since Vagrant likes to reload its mounts/shared folders on each load.

I hope this helps!

like image 2
David Myers Avatar answered Nov 04 '22 16:11

David Myers