Rocking with tmux, tmuxinator, Guard, Zeus, and iTerm2 for Rails Development
What's the most effective way to:
- Start several different processes for Rails, such as Zeus, Rails server, rspec, resque, and the scheduler.
- Have the output for each process in a separate tab.
- 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:
- 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. - 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.
# First brew install tmux, gem install tmuxinator, and download item2
# Copy this file here: ~/.tmuxinator/my_project.yml
# Modify the paths (replace ~/my_project with your directory)
# Invoke with
# mux project
# Then hit 'Ctrl-a d' to detach
# Then run 'tmux -CC attach'
# Make sure that option for iterm2 is General --> tmux --> When attaching, open unrecognized windows in Tabs
# Also, check option "Automatically hide the tmux client session after connecting"
# alias beg='bundle exec guard'
# define guard groups for spec, server, worker
name: project
pre_window: cd ~/my_project
root: ~/my_project
windows:
- zeus: zeus start
- spec: beg -g spec
- server: beg -g server
- worker:
layout: main-horizontal
panes:
- beg -g worker
- scheduler
When I run the command
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:
- 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.
- 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:
- Start tmuxinator with command
mux my_project
- Hit
ctrl-a, d
to detach the tmux process. - Run command =tmux -CC attach"
Here's how it will look:
If you want to kill the session, you can run this command:
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.
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.