ShakaCode | ShakaCode Blog | Rails On Maui Blog | Rails | ReactJs | JavaScript | Webpack | Productivity |

Rocking With Tmux, Tmuxinator, Guard, Zeus, and iTerm2 for Rails Development


#1

What’s the most effective way to:

  1. Start several different processes for Rails, such as Zeus, Rails server, rspec, resque, and the scheduler.
  2. Have the output for each process in a separate tab.
  3. Not have the process pause when you scroll the output, as happens in tmux.

Here’s a short demo of using tmuxinator to get a project running in several iterm2 tabs:

Why Guard?

I use Guard for:

  1. Automatically running rspec tests based on changes in either tests or source files. Together with Zeus, I haven’t found a faster way to get immediate feedback from tests. Pro tip: Learn how to use :focus with your specs to configure exactly what tests to have guard run.
  2. Automatically restarting the server when needed. For example, if you change gems or routes, you need to restart the server.

While I love running Guard with Zeus, Spring is the default in Rails 4.1, so I’ll probably give that a try in the near future.

Why Tmuxinator and Tmux?

Tmuxinator is awesome for configuring the layout of several processes.

Here’s a sample tmuxinator file.

When I run the command

1
mux my_project

And then I see the following. This is way easier than opening up tabs in iTerm2 and running commands every time.

The main problem with this setup is that if you scroll a window backwards (using the tmux keyboard bindings), and you don’t un-scroll, then the process pauses, such as the Rails server. That’s super annoying. Often I’m running specs, and I want to scroll back to see a stack trace, but that prevents the continuation of the test run! Here’s a short discussion of the issue.

iTerm2 with tmux to the Rescue!

iTerm2 has wonderful tmux integration. Here’s the steps I take:

  1. Be sure have the latest versions of tmux, tmuxinator and iTerm2. As of this article, I’m using: tmux: 1.9a, tmuxinator: 0.6.7, iTerm2: Build 1.0.0.20140112.
  2. Configure your Tmux to open tabs rather than windows. This is key to getting the iTerm2 version to look like your original tmux session.

Once you have the setup done, this is how I start my iTerm2-tmuxinator session:

  1. Start tmuxinator with command mux my_project
  2. Hit ctrl-a, d to detach the tmux process.
  3. Run command =tmux -CC attach”

Here’s how it will look:

If you want to kill the session, you can run this command:

1
tmux kill-session -t my_project

However, that sometimes does not kill all the processes. I often use these two zsh scripts to ensure that everything is killed. It’s super important to kill Zeus before running db migrations or gem updates.

1
2
3
4
5
6
7
8
9
10
11
pgr() {
  for x in rails phantomjs zeus; do 
    pgrep -fl $x;
  done
}

pgk() {
  for x in rails phantomjs zeus; do 
    pkill -fl $x;
  done
}

Why Tmuxinator/tmux and not Foreman?

I use Foreman with Heroku and for running my rails server in production mode. However, I prefer having different tabs provide console output for each of the processes, rather than having all the console output blended together as Foreman does. I’m also not sure if Foreman integrates with Guard.


This is a companion discussion topic for the original entry at http://www.railsonmaui.com//blog/2014/03/11/rocking-with-tmux-tmuxinator-and-iterm2-for-rails-development/

#2

Great post. Inspired me to give Zeus and tmux a shot again. Really liking it.


#3

Great post ! However I can't get my tmux windows opened in iterm tabs... It opens one tab per window (Build 1.0.0.20140518 for iterm) even if I check the option to open in tabs... it's frustating, do you any idea why it's not working ?


#4

It works now ! I needed to install the last version of tmux (not working with 1.7) and restart Iterm. Thanks !


#5

I can verify that Foreman integrates with Guard, as I'm currently using them that way.


#6

This article inspired me to make the switch to iTerm + Tmux as well. Soooooo much better. However, I ran into one tiny snag. I use TextMate and Guard (under Tmux) only responds to file changes made within that Tmux session. Couldn’t find any solutions on the interwebs. Any workarounds?


#7

@ccmcbeck, that doesn’t seem right. If file changes are saved, they’ll be visible everywhere. It could be something to do with textmate, as I’ve never used textmate.


#8

Thanks for the quick response. On closer examination, I was confused about the actual problem. Guard IS firing on any change by any program inside or outside of tmux. My issue is that inside tmux, Guard hangs after the first time it fires. IOW, it doesn’t return back to a a ‘guard >’ prompt. If I press Ctrl+C, Guard returns back to the ‘guard >’ prompt and will fire the next time before hanging again. I’ll try removing things until I find the culprit.


#9

add this to your tmuxinator config file to skip the detach and reattach routine:

attach: false
post: tmux -CC attach