Très
Très

Reputation: 804

Run a command in the context of a different app

I have two rails apps on the same server, let's call them A and B.

I am trying to have app A restart app B via app B's own capistrano task. Unfortunately, even after cd-ing to app B's directory, it is trying to run app A's capistrano instead. Am I missing something?

example code

system("cd /apps/appB/current && pwd && bundle exec cap:restart")

pwd correctly returns the path of appB (/apps/appB/current), however, in there is a traceback for cap:restart. This is because it is still trying to run the cap command in the context of appA, e.g.

/apps/appA/shared/bundle/ruby/1.9.1/gems/capistrano-2.15.4/lib/capistrano/configuration/loading.rb:152:in 'require': cannot load such file -- airbrake/capistrano (LoadError) from /apps/appA/shared/bundle/ruby/1.9.1/gems/capistrano-2.15.4/lib/capistrano/configuration/loading.rb:152:in 'require'.

I tried without 'bundle exec', and have tried some other ways of making system calls. I also created a bash script in another directory and tried to run it that way.

All methods described exhibit the same behaviour.

Your help would be greatly appreciated =)

Upvotes: 1

Views: 243

Answers (2)

Tim Moore
Tim Moore

Reputation: 9482

You need to use Bundler.with_clean_env to ensure that your subprocess doesn't pick up your current Bundler environment:

Bundler.with_clean_env do
  system("cd /apps/appB/current && pwd && bundle exec cap:restart")
end

This is essentially the same problem as Install bundle of gem within other rails application

Upvotes: 1

bratsche
bratsche

Reputation: 2674

Since you said your apps are using Unicorn, you can signal from app A to app B (or the other way around).

Read this page: http://unicorn.bogomips.org/SIGNALS.html

The only thing each application needs to know is the pidfile path of the other application. So look at your Unicorn config and see where it's storing that.

You could either read the PID out of that pidfile and kill it from Ruby:

pid = File.read(path_to_other_application_pidfile).chop
Process.kill("USR2", pid)

Or you could use backticks to execute shell commands

`kill -s USR2 \`cat #{path_to_other_application_pidfile}\``

Upvotes: 0

Related Questions