Introducing Invoker - Manage processes in development envionment

Hemant's avatar

Hemant

If you are working on a large application with several dependencies such as - more than one application server, background job, it can get tedious to start and stop and check their logs in bunch of different places.

Invoker is a small utility we wrote to manage all such processes from one place. Invoker owes much to Foreman for inspiration, however unlike Foreman it has been exclusively written to be used in development environment. Some major differences are:

  • If one process managed by invoker crashes, it doesn't crash entire process manager.
  • Error reporting is much better. Crashed processes do not just exit with a cryptic error, but they will print their full error.
  • To start/stop/restart individual process in the group, you no longer need to restart entire process manager.

To get started we need to install invoker gem which will give us command line utility called invoker, we can do that via:

gem install invoker

Currently it only works with Ruby 1.9.3 and 2.0.

After that we need to start by creating a ini file which will define processes we want to manage using invoker. For example:

[rails] directory = /home/gnufied/god_particle command = zsh -c 'bundle exec rails s -p 5000'

[dj] directory = /home/gnufied/god_particle command = zsh -c 'bundle exec ruby script/delayed_job'

[events] directory = /home/gnufied/god_particle command = zsh -c 'bundle exec ruby script/event_server'

After that we can start process manager via:

~> invoker start invoker.ini

Above command will start all your processes in one terminal with their stdout/stderr merged and labelled.

Now additionally we can control individual process by,

Will try to stop running delayed job by sending SIGINT to the process

~> invoker remove dj

If Process can't be killed by SIGINT send a custom signal

~> invoker remove dj -s 9

add and start running

~> invoker add dj

One can also enable OSX notifications for crashed processes by installing terminal-notification gem. It is not a dependency, but can be useful if something crashed and you weren't paying attention.

Using with rbenv or rvm

The way rbenv and rvm work sometimes creates problems when you are trying to use a process supervisor like invoker. There are couple of things to keep in mind, If you are running invoker with Ruby version x, but your application requires Ruby version Y:

  • When using rbenv, you can define the command with environment variable RBENV_VERSION=Y and then start your application. In other words:

    command = RBENV_VERSION=2.0.0-p0 zsh -c "bundle exec rails s"

  • Unless version of Ruby using which you are running invoker command and version of Ruby you are using in the application is same, you almost always will want to use zsh -c or bash -c. RVM in particular requires a login shell and hence sometimes you may have to use bash -lc. For example:

    command = bash -lc "rvm use 2.0.0-p0 && bundle exec rails s"

I hope you find this gem useful and do not forget to follow us on twitter @codemancershq if you want to keep up with latest utility we are making to make our lives wee bit easier.

Source Code