Efficient Drupal Development with Tmux and Tmuxinator
Have you ever wished you could just type one command and load up all of the things you need to work on for a project? Wouldn’t it be nice to have your terminal set up with the correct Drush alias, tailing the watchdog, with access to your servers just a couple keystrokes away? Sounds nice, right? With a little work and a handful of open source applications this can be a reality for you.
When I need to get started on one of my projects it’s as simple as typing mux projectname and I pick up right where I left off the previous day. Here’s how I do it.
The cornerstone application that I use every day is a terminal multiplexer called Tmux. It allows you to quickly switch between multiple terminal programs using key commands. One on my favorite features of tmux are the multi-pane windows. You can divvy up your terminal window into two, three, or more panes. Each one running it’s own terminal session. While this is useful enough, its true utility is its ability to detach from a session without interrupting or canceling it. For example, let’s say you are downloading a large file with wget on a server and want to check something else on your local machine while you wait. You can do so without opening a new terminal window by detaching from your tmux session. Your download will continue in the background. Then, when you are ready to resume work on your server simply re-attach to your tmux session.
That all sounds great, but how can this application help me with my local development work? This is where Tmuxinator comes in. Tmuxinator provides a method for creating and managing tmux sessions. I can’t imaging using tmux without it. I have a default template that I begin with on every project. It includes my terminal layouts, commands I need to run when beginning work, and windows for development, staging, and production servers, and setting up each pane with the proper Drush or bash alias.
On a Mac you can quickly install Tmux using Homebrew.
brew install tmux
Once you have tmux installed you will want to take a look at the post on the Thoughtbot’s blog “A tmux Crash Course” and set up your own keybinding configuration. Then you will want to set up copy and paste to work as it does in Vim by following this Thoughtbot tutorial. If you are on Linux you may find that you don’t need some of these configuration changes. Specifically the copy and paste settings. I have included my .tmux.conf file below. Note, this file is located in your home directory and is a dot file so it will be hidden in most file browsers.
My .tmux.conf file
# Use vi mode setw -g mode-keys vi # fix pbcopy and pbpaste set-option -g default-command "reattach-to-user-namespace -l bash" # Setup 'v' to begin selection as in Vim bind-key -t vi-copy v begin-selection bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy" # Update default binding of `Enter` to also use copy-pipe unbind -t vi-copy Enter bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy" # force a reload of the config file unbind r bind r source-file ~/.tmux.conf # mouse scrolling and selection set -g mode-mouse on set -g default-terminal "screen-256color"
Now you should be ready to use Tmux, but let’s also set up Tmuxinator. Tmuxinator is a Ruby gem and can be installed with the command
gem install tmuxinator but do follow the instructions on the project page.
Setting up your first project
Now, let’s set up a new Tmuxinator project by typing mux new awesome_project. This will open up your project file in your default text editor.
# ~/.tmuxinator/awesome_project.yml name: awesome_project root: ~/ # Optional tmux socket # socket_name: foo # Runs before everything. Use it to start daemons etc. # pre: sudo /etc/rc.d/mysqld start # Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions. # pre_window: rbenv shell 2.0.0-p247 # Pass command line options to tmux. Useful for specifying a different tmux.conf. # tmux_options: -f ~/.tmux.mac.conf # Change the command to call tmux. This can be used by derivatives/wrappers like byobu. # tmux_command: byobu windows: - editor: layout: main-vertical panes: - vim - guard - server: bundle exec rails s - logs: tail -f log/development.log
Each tab in tmux is called a window. You can assign names to these windows which helps you remember what a window is used for. Inside each tmux window is one or more panes. The default configuration that Tmuxinator provides is very Ruby on Rails specific so let’s change that. Here is a more Drupal specific tmuxinator project setup.
# ~/.tmuxinator/awesome_project.yml # you can make as many tabs as you wish… project_name: awesome_project project_root: ~/Sites/awesome_project windows: - drupal: layout: main-vertical panes: - cd docroot && pstorm . && drush use @awesome.mcdev && git status - cd docroot && drush use @awesome.mcdev && drush ws --tail - cd mis_vagrant && vagrant up - tig: cd docroot && tig - dev: alias drush="/usr/local/bin/drush/drush" && drush use @drupalplatformprovider.awesome.dev - staging: alias drush="/usr/local/bin/drush/drush" && drush use @drupalplatformprovider.awesome.test - prod: alias drush="/usr/local/bin/drush/drush" && drush use @drupalplatformprovider.awesome.live
Once you have made your changes save and close the project file. Type mux awesome_project to begin you first tmux session.
You will notice that I have several windows. Specifically, I want to point out the dev/staging/prod windows. I like to use drush aliases and with Tmuxinator you can execute terminal commands when you launch the session. Let me walk through what the tmuxinator project file is actually doing.
- Pane 1: I cd to docroot and open that directory in PHPStorm. You can substitute this command for your editor of choice.
- Pane 2: I cd to docroot and set drush to use my local alias then tail the drupal watchdog with drush use @awesome.mcdev && drush ws –tail.
- Pane 3: launches my vagrant box for this project
I cd to docroot and execute the Tig application which shows me a list of commits to the repository in the command line.
Dev / Stage / Prod
On many projects our clients may be using a Drupal platform service such as Pantheon or Acquia Cloud. Some server environments may require the use of older versions of Drush than say Drush 7. I will have Tmuxinator set up each terminal window with the proper shell alias to my desired drush version and also the drush alias for that server.
Is it worth it?
While this may seem like quite a bit of work to set up the efficiency you can achieve with this workflow will quickly become apparent.
How To Prettify the Output From Your Remote Drush Commands | Mediacurrent Blog Post
Learning How To Install Drush on Non-Admin Rights Server | Mediacurrent Blog Post
A Better Access Denied Page with Panels | Mediacurrent Blog Post