How do we run some OS command when Rails is starting? - ruby-on-rails

I need to run a command after or before starting Rails. It will start a server on port 9292 so my chat app will work.
This command should preferably be executed automatically with Rails (on production and development).
How do we do that in Rails 4?
Is Capistrano the only option? Can we schedule it to be executed when Rails starts?

Use capistrano and forman or systemd to manage your chat server instance, like, for example you would do for sidekiq.
A good start would be : http://anlek.com/2015/01/using-foreman-with-upstart-capistrano/

You have 2 options that I know of if you don't want to use Capistrano. In your config/application.rb
config.after_initialize do
# ....
end
http://guides.rubyonrails.org/configuring.html
or you can write a custom initializer that is run with on_server_start event.

There's a whole section of config/ intended for startup behavior: config/initializers/. If you need to do anything as part of the startup of your app, you can create an initializer file here, and it will automatically get run as Rails starts.
To do this, simply create a new file: config/initializers/chat_app.rb:
# This file will start and establish an initial connection to the chat app
`chat-app --some-arg` # <== The chat app
We use this for various startup and system sanity checks for the application. It's independent of your deployment, so if you need it for other deployment purposes, creating a Capistrano (or even Rake) task is the better option.

Related

Rails: How to run code when server starts up, but not when running a rake task or the console?

Before, I added code to a file called config/initializers/remote_publishers.rb which set up a connection to RabbitMQ using the Bunny gem on server startup.
However, this is now also executed when running rails c, rails g model SomeModel foo:integer, rails db:migrate etc.
For this app, the RabbitMQ-connection only makes sense when rails is started using rails s(erver).
What is the proper way to conditionally execute this code? Is there a way to see if Rails is starting as server, or only as task-runner?
What web server are you using? On Puma, for example, you can use
on_worker_boot do
# Establish RabbitMQ connection
end
Another possibility might be to check if defined?(Rails::Server) in your initializer: this should only be true when running in the context of the web server.

start thinking sphinx on rails server startup

I have a chain of nginx + passenger for my rails app.
Now after each server restart i need to write in terminal in project folder
rake ts:start
but how can i automatize it?
So that after each server restart thinking sphinx is automatically started without my command in terminal?
I use rails 3.2.8 and ubuntu 12.04.
I can not imagine what can i try ever, please help me.
How can i do this, give some advices?
What I did to solve the same problem:
In config/application.rb, add:
module Rails
def self.rake?
!!#rake
end
def self.rake=(value)
#rake = !!value
end
end
In Rakefile, add this line:
Rails.rake = true
Finally, in config/initializers/start_thinking_sphinx.rb put:
unless Rails.rake?
begin
# Prope ts connection
ThinkingSphinx.search "test", :populate => true
rescue Mysql2::Error => err
puts ">>> ThinkingSphinx is unavailable. Trying to start .."
MyApp::Application.load_tasks
Rake::Task['ts:start'].invoke
end
end
(Replace MyApp above with your app's name)
Seems to work so far, but if I encounter any issues I'll post back here.
Obviously, the above doesn't take care of monitoring that the server stays up. You might want to do that separately. Or an alternative could be to manage the service with Upstart.
If you are using the excellent whenever gem to manage your crontab, you can just put
every :reboot do
rake "ts:start"
end
in your schedule.rb and it seems to work great. I just tested on an EC2 instance running Ubuntu 14.04.
There's two options I can think of.
You could look at how Ubuntu manages start-up scripts and add one for this (perhaps in /etc/init?).
You could set up monit or another monitoring tool and have it keep Sphinx running. Monit should boot automatically when your server restarts, and so it should ensure Sphinx (and anything else it's tracking) is running.
The catch with Monit and other such tools is that when you deliberately stop Sphinx (say, to update configuration structure and corresponding index changes), it might start it up again before it's appropriate. So I think you should start with the first of these two options - I just don't know a great deal about the finer points of that approach.
I followed #pat's suggestion and wrote a script to start ThinkingSphinx whenever the server boots up. You can see it as a gist -
https://gist.github.com/declan/4b7cc4fb4926df16f54c
We're using Capistrano for deployment to Ubuntu 14.04, and you may need to modify the path and user name to match your server setup. Otherwise, all you need to do is
Put this script into /etc/init.d/thinking_sphinx
Confirm that the script works: calling /etc/init.d/thinking_sphinx start on the command line should start ThinkingSphinx for your app, and /etc/init.d/thinking_sphinx stop should stop it
Tell Ubuntu to run this script automatically on startup: update-rc.d thinking_sphinx defaults
There's a good post on debian-administration.org called making scripts run at boot time that has more details.

Detect if application was started as HTTP server or not (rake task, rconsole etc)

I'm using EventMachine and Monetarily to start e TCP server along with my rails application. This is started from config/initializers/momentarily.rb.
My problem is that it starts also when I run rake tasks, like db:migrate. I only want it to start when when I start the HTTP server. Environments won't help, since both the server start and rake tasks are under Development environment. Is there a way of knowing that the application is running the HTTP server as opposed to anything else? Note that is not only rake tasks, the EM starts also if I run the rails console, which is again something not desirable for my case.
unless File.basename($0) == "rake" && ARGV.include?("db:migrate")
# you are not in rake db:migrate
end
There's not a great way of doing this that I know of. You could copy newrelic's approach (check discover_dispatcher in local_environment.rb) which basically has a list of heuristics used to detect if it is running inside passenger, thin, etc.
For passenger it checks
defined?(::PhusionPassenger)
for thin it checks
if defined?(::Thin) && defined?(::Thin::Server)
Set an environment variable in config.ru file, and use it anywhere in the code to detect if it's executed using a rails server command only.
For e.g.
File: config.ru
ENV['server_mode'] = '1'
And using it somewhere as:
File: config/environment.rb
Thread.new { infinite_loop! }.join if ENV['server_mode'] = '1'
Reference: Answer
Maybe you can implement a switch in the initializer based on ARGV?
Something like:
if ARGV.join(' ').match /something/
# your initializer code here
end
Don't start that other server from an initializer. Create a daemon in script/momentarily and start it from within your app.
After your application launches, you could have it shell out to check ps. If ps shows that the HTTP server is running and the running HTTP server has the same pid as your application (check the pid by inspecting $$), then you could launch the TCP server.
In addition to a great answer by Frederick Cheung above, there can be some other "footprints" in actual process environment. Eg. Phusion Passenger adds certain variables to ENV such as:
PASSENGER_APP_ENV
IN_PASSENGER
PASSENGER_SPAWN_WORK_DIR
PASSENGER_USE_FEEDBACK_FD
Web servers typically can also set SERVER_SOFTWARE variable eg.:
SERVER_SOFTWARE=nginx/1.15.8 Phusion_Passenger/6.0.2

Start up required additional services (resque, redis) with `rails server` command

I would like my development environment for Rails to automatically start redis and resque (and potentially in other projects, mongod, mysql-server etc.) for me, in the following cases:
When starting up the development server rails server.
Additionally, it would be nice if the following cases detect already running services, and, if not running start them up too:
Rake rspec, rspec /spec, when running tests.
When starting up a rails console.
When shutting down the rails server, the started child-services should be shut down too.
What is the correct place for such additional startup scripts?
And how to avoid them being started in production too (where I run everything trough /etc/init.d services)?
A lot of these built-in tasks are available as rake tasks already.
You can create a master rake task that does it all.
For example, with resque, you get "rake resque:start" "rake resque:scheduler:start", etc.
You can create a generic "start" task that depends on the rest. Similarly, a "stop" task would shut everything down.
So you would do:
rake start # starts all associated processes
rake stop # stops them all
This is also very use to use from Capistrano, when you end up deploying your code somewhere else. Rake tasks are very easy to call from Capistrano.
I think it's really better to do that in some external script. Do it in your rails server command can be really annoying to anyone to try your code.
By example, in one year, a nez developper come to your project. He can be desoriented if your rails server commande launch a such of other application in background.
In same idea, if you do that you need maintain your code in your rails env. Can be a little tricky. Maintain an independant script can be more usefull.
You can add your script in script directory. That be a good pratice. But not when you launch a command with a manual who do not that.

Daemon Start at the application bootup

I have a daemon that should run behind my rails app doing db modifications.I implemented that daemon using ruby daemons gem. I want to start that daemon at the start of my app. Whenever my app starts, I need to start that daemon.
How can I do this..?
If you must start it during Rails initialization:
Create a ruby file that will start the daemon. Say invoke_daemon.rb
Put this file in config/initializers/invoke_daemon.rb
However if it isn't mandatory, I would suggest creating a binary executable or a rake task and manually starting it through command line. This way it runs as a separate process. You can simply add it to your deployment scripts for production boxes and on development box run it manually. A few examples would be searchd, the search daemon for sphinx and thinking_sphinx:delayed_delta rake task from thinking_sphinx.
For your knowledge you have to take look of
Rails Life cycle
I have just implemented this thing. I have implemented on Windows7.
I have created one batch file let's say my_batch.bat, which contains ruby command i.e. ruby my_daemon.rb file.
In addition, to execute this file when my app starts , I have just added one statement in environment.rb file which executes that batch file. i.e. system ("my_batch.bat").
But I am not sure that this is a good way to implement this task.

Resources