Skip to content

Instantly share code, notes, and snippets.

@todgru
Last active February 26, 2016 23:47
Show Gist options
  • Select an option

  • Save todgru/fe6a7fa90d7d20eddc7b to your computer and use it in GitHub Desktop.

Select an option

Save todgru/fe6a7fa90d7d20eddc7b to your computer and use it in GitHub Desktop.
Use Netcat to restart Puma service in Vagrant from OS X

Problem

We had a heck of a time getting Guard, Shotgun, or Rerun to work with our Nginx/Puma/Grape API in a Vagrant and OS X development environment. inotifywatch was no use. We tried Grape-Reload. I could not get it behave the way I wanted. Maybe this was because we aren't using Rails. Imagine.

Many restart/reload type gems and inotify depend on the OS kernel to let them know a file has changed. If a file is changed from outside of the file system, like OS X and Vagrant "shared" paths, the Vagrant kernel doesn't see the changes.

Solution

Here is the solution we came up with using Netcat.

On the Vagrant box we have Netcat running, listening to port 9001. When the port receives a restart string, Puma is killed off and restarted.

On the host environment - OS X - we have fswatch running. Anytime a file is changed in our project directory, a restart string is sent on port 9001.

Code

Vagrant server code:

#!/bin/bash
# start puma, get the pid
exec bundle exec puma config.ru -e development -b unix:///var/run/ruby-api.sock & puma_pid=$!

# start netcat server, listen for "restart" command
netcat -lk -p 9001 | while read line; do
    # there is a cleaner way of doing this with grep. wouldn't work for me.
    if [ "$line" == "restart" ]
    then
        # restart command found!
        echo "File system change. Restarting Puma."
        kill $puma_pid
        exec bundle exec puma config.ru -e development -b unix:///var/run/ruby-api.sock & puma_pid=$!
    fi
done

OS X watch code:

Install fswatch

$ brew install fswatch

Run the watcher in the background.

$ fswatch -or /path/to/watch/ |  xargs -n1 -I{} echo 'restart' | nc localhost 9001 > /dev/null &

💥

Notes and gotchas

  • Make sure you have port 9001 open on your Vagrant machine. Something like: config.vm.network "forwarded_port", guest: 9001, host: 9001
  • Start Vagrant Netcat process FIRST, then start the watcher. Without Netcat running a server on Vagrant, the watcher will have nothing to connect to.
  • Sometimes there is a few second delay on restarts when fswatch notices a file has changed, which delays sending the restart command to Vagrant.
  • Depending how your environments are set up, localhost may not work for you. Try 127.0.0.1.

Sources

I hacked this together using work from the following url's as well a bunch of other things I can't remember how I learned them:

Follow-up

Please send feedback and let me know how it works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment