Guard --listen-on with vagrant

2019-03-29 05:51发布

问题:

I am trying to use guard's --listen-on option with vagrant as outlined here, but I am unable to get it to work.

If I add config.vm.network :forwarded_port, guest: 4000, host: 4000 to my Vagrantfile and subsequently try to start listen with listen -f 127.0.0.1:4000, I get an error: Broadcaster.initialize: Address already in use - bind(2) for "127.0.0.1" port 4000.

If I try to start listen and then start vagrant, vagrant complains similarly:

Vagrant cannot forward the specified ports on this VM, since they would collide with some other application that is already listening on these ports. The forwarded port to 4000 is already in use on the host machine.

So I tried some other things while omitting the port 4000 forwarding in the Vagrantfile:

If I omit the port 4000 forwarding in my Vagrantfile, then I can successfully start listen with listen -f 127.0.0.1:4000. But then when I run guard -o "10.0.2.2:4000" -w "/home/me/my_project/" in my vagrant guest, guard does not do anything when a file changes. Adding a -v flag to the listen call reveals that changes are being picked up correctly on the host.

I also tried listen -f 10.11.12.1:4000 on the host combined with guard -o "10.11.12.1:4000" -w "/home/me/my_project/" on the guest with the same results of guard not do anything when a file changes.

Combining listen -f 127.0.0.1:4000 with guard -o "10.11.12.1:4000" -w "/home/me/my_project/" results in guard being unable to connect.

I've also tried port forwarding with ssh:

listen -vf 127.0.0.1:4000 # host
ssh -R 4000:localhost:4000 vagrant@10.11.12.13 # connect
guard -o "127.0.0.1:4000" -w "/home/me/my_project" # guest

Everything seems to go okay with port forwarding, but again guard never does anything when files are changed.

Both the host and guest are ubuntu 14.04.

The network config in my Vagrantfile is as follows:

config.vm.network 'forwarded_port', guest: 80,   host: 3000
config.vm.network 'private_network', ip: '10.11.12.13'

What is the proper way to make this work?

回答1:

UPDATE 2:

Listen 3.x no longer includes TCP functionality (see https://github.com/guard/listen/issues/258), so you'll need to lock to 2.x, e.g. in your Gemfile:

gem 'listen', '~> 2.9'

And then follow the instructions below:

UPDATE 1:

For guard >= v2.7.0 to work, you need listen >= v2.9.0 and the magic -r option (since full paths don't match on host and guest):

listen -r -f 10.11.12.1:4000 # on the host (note "-r" option)
guard -o 10.11.12.1:4000 # on the guest (paths relative, so no prob)

Notes:

  • since guard v2.7.0, -w is only for listening for multiple directories. Instead, run listen in the directory you're watching

  • I'd only consider Vargrant/ssh forwarding only if you're behind a firewall, or you can't use the given ports for some reason - instead, use the VM assigned IPs and network (e.g. 10.11.12.1)

  • for debugging things in guard, check out: https://github.com/guard/guard/wiki/Understanding-Guard (worth taking a look)

  • running a listen TCP server on 127.0.0.1 makes little sense (unless e.g. you must use a complex ssh port forwarding setup)



回答2:

See Cezary Baginski's answer for a more concise answer and how to make this work with newer (>= 2.7.0) versions of guard. I am going to leave this answer up for context.


Armed with Cezary Baginski's advice for how the networking should work and still being unable to get this setup working, I proceeded to investigate further with the assumption that something must have broken between Jamie Lawrence's implementation / blog post and now.

So I decided to downgrade guard and listen to versions released around the same time frame (February 24, 2014). That gave me:

gem 'guard', '2.5.1'
gem 'listen', '2.6.1'

I ran into an error after that that I solved by downgrading guard-rspec to a version from around the same time period:

gem 'guard-rspec', '4.2.8'

I was still receiving a (different) error, so I regenerated a new Guardfile with guard init rspec. Note that prior to this, guard ran perfectly fine on the host and worked on the guest with polling or rsync (though the polling/rsync performance was abysmal) - the Guardfile was not the problem.

So after that came the moment of truth:

listen -f 10.11.12.1:4000 # on the host
guard -o 10.11.12.1:4000 -w "/home/me/my_project" # on the guest

Finally, I had gotten this to work.

I then went through the guard releases from 2.5.1 to 2.12.4 in a binary search fashion to try determine where something may have broken. What I found was this just stops working in guard > 2.6.1.

# works
gem 'guard', '2.6.1'
gem 'listen', '2.8.6'
gem 'guard-rspec', '4.2.8'

# does not work
gem 'guard', '2.7.0'
gem 'listen', '2.8.6'
gem 'guard-rspec', '4.2.8'

I think this is as good as it gets for now. I have filed a bug with guard.



回答3:

I've also had the same issues and I solved the problem just installing: https://github.com/mhallin/vagrant-notify-forwarder Which automatically forwards fs file changes to vagrant vm

Hope it helps



回答4:

I use Vagrant on MacOS to develop rails applications. I have been using NFS to sync folders btwn my Mac(host) and Virtualbox Vm(guest). I ran into many issues when trying to use the LISTEN gem on my Mac to send filesystem change notifications to GUARD on the virtual machine.

For me, the best solution was to change the folder sync method in Vagrant to "rsync" as described here. Now, because files are actually on the VM, the latest version of Guard works fine and there's no complicated passing of filesystem changes on the host to the VM using tcp.

The only problem I've observed so far is that sync'ing btwn mac and VM is not instantaneous, particularly if the (vagrant defined) synced folder is large. For me, the delay is acceptable (1-2 secs).