Restart rails server on git commit - ruby-on-rails

I'm setting up a shared development server for a Ruby on Rails project.
Is there a good way to set it up to restart, or reload the code every time someone pushes a commit to the master branch (for example)? I don't care about setting up gems etc every time, à la Heroku - I just want to run the new code.
If there are any problems, I can go in and restart the server manually - I just don't want to do it every time.

The post-receive hook runs after the entire process is completed and can be used to update other services or notify users.
In the post-receive hook, you'll most likely need to grep for the Ruby PID, kill that process and then restart the Rails server.

Git Hooks is what you're looking for.
Using these, you can run custom commands based on certain conditions.
Create a file named post-commit under your .git/hooks folder like so:
#!/bin/sh
exec rake deploy
and in your Rakefile,
task :deploy do
pid = IO.open("ps").grep(/script\/rails/) { |x| x.split(" ").first }.first
sh "kill -9 #{pid}"
sh "rails s"
end

Related

How to monitor heroku worker dyno?

I usually just run "heroku run rake jobs:work" from the command line. The great thing about this apporach is that I get intimidate feedback on whether a job failed or not and what jobs are currently processing.
However, now I need to run "heroku ps:scale worker=1"
Is there a way to see what the worker is processing just like with the rake task via the command line?
You can use the heroku command like to access the log of the worker.
heroku logs -t --ps worker will show you what is currently being executed on your worker.
I also recommend to use gem workless which scales your worker up only when needed. This can save you a lot of money
You didn't say specifically what queue you are running, but it sounds like delayed_job. If so, you can install the delayed_job_web gem. Basic setup is as simple as adding it you your Gemfile and adding a route for it. Then you can browser to your site /delayed_job and manage the jobs.

What's the better way to execute daemons when Rails server runing

I have some gems in my Rails App, such as resque, sunspot. I run the following command manually when the machines boots:
rake sunspot:solr:start
/usr/local/bin/redis-server /usr/local/etc/redis.conf
rake resque:work QUEUE='*'
Is there a better practice to run these daemon in the background? And is there any side-effect when run these tasks run in the background?
My solution to that is to use a mix of god, capistrano and whenever. A specific problem I have is that I want all app processes to be run as user, so initd scripts are not an option (this could be done, but it's quite a pain of user switching / environment loading).
God
The basic idea is to use god to start / restart / monitor processes. God may be difficult to get start with, but is very powerful :
running god alone will start all your processes (webserver, bg jobs, whatever)
it can detect a process crashed and restart it
you can group processes and batch restart them (staging, production, background, devops, etc)
Whenever
You still have to start god on server restart. A good mean to do so is to use user crontab. Most cron implementation have a special instruction called #reboot, which allows you to run a specific command on server restart :
#reboot /bin/bash -l -c 'cd /home/my_app && SERVER=true god -c production/current/config/app.god"
Whenever is a gem that allows easy management for crontab, including generating reboot command. While it's not absolutely necessary for achieving what I describe, it's really useful for its capistrano integration.
Capistrano
You not only want to start your processes on server restart, you also want to restart them on deploy. If your background jobs code is not up to date, problem will arise.
Capistrano allows to easily handle that, just ask god to restart the whole group (like : god restart production) in a post deploy capistrano task, and it will be handled seamlessly.
Whenever's capistrano integration also ensure your crontab is always up to date, updating it if you changed your config/schedule.rb file.
You can use something like foreman to manage these processes. You can define process types and other things in a Procfile and you can start and do whatever with them.

Rails: start script on server and then "leave"

I want to run a rake script on my application on Heroku that will take several hours. If I start it from my console on my laptop, and shut down my laptop the script will stop (and I will have to shut down my laptop before the script is finished).
How do I do to start this rake script without it being "tied" to my laptop. I.e. so that it continues to run until it breaks or is finished?
heroku run rake update_feeds_complete --app myapp
is the script to run...
Giving me advice on what commands etc to Google would be helpful as well.
You can run commands with run:detached and close the terminal window and they will continue to run. So you simply need to run
heroku run:detached rake update_feeds_complete --app myapp
You might want to take a look at the scheduler, too. https://devcenter.heroku.com/articles/scheduler
Pretty handy for running rake tasks, even if one-offs.
In general, I use resque and redis for jobs I want to run on heroku. If it's a one-time job I may not, but if it's something I'm going to do regularly then having them installed is a great convenience.
redis installs through the 'Redis To Go' add-on with Heroku.
resque is a gem that's used for running background jobs of different kinds. There are lots of plugins for resque for sending email, for job scheduling, etc.
I'm not familiar with Heroku in particular, but in the past when i have run into this case I used remote execute via SSH:
ssh username#your.server -f 'your command here'
This will open an ssh session, execute your command and then close the connection. But your script will keep running remotely.

How to autostart Rails delayed jobs?

I'm using delayed job to create job queues such as 'mailer'
For this to work I have to run this:
$ RAILS_ENV=development QUEUE=mailer rake jobs:work
But if the server crashes and is restarted, I need the worker to start running again automatically.
What would be the recommended way to deal with this?
You need to use a third-party service like monit/bluepill/god/upstart to watch the process and restart it. I recommend using the combination of foreman and upstart. See here: http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
Some time ago I wrote a patch for the DelayedJob to reload the classes for every job in development mode. Same patch should work for your requirement also.
betamatt's approach is definitely one way to do it if you have such a monitoring tool in place.
Another way to do it would simply be to add a script to your OS's startup which runs the RAILS_ENV=development QUEUE=mailer rake jobs:work command under a user who has the necessary permissions.
Here's an example of how to do it on Ubuntu using Upstart, but if you lookup similar init.d methods, or whatever is the relevant for your server OS, you'll find other ways. What you're looking for, basically, is "How to run a script on startup [your OS name]", and then wrap your command in an executable script.
I had the same issue with my application am working with. So i wrote a rake task which runs every minute(as a cron job). When delayed job starts it will create a .pid file in the temp folder. I used this to check the existence of a delayed job process. If the file doesn't exist i ran the console command through code.
delayed_job_status = File.file?("./tmp/pids/delayed_job.pid")
This will check the existence of process. If nil response go to next statement
./bundle exec script/delayed_job start production
This will start delayed job
My solution was creating the bash script in user's home "delayed_job_startup.sh"
which contain
#!/bin/bash
cd /home/deploy/project/current/
RAILS_ENV=production bin/delayed_job start
and in file /etc/rc.local I run this script from my user
su -s /bin/bash - deploy /home/deploy/delayed_job_startup.sh

Capistrano deploy but manually run migrations

I'm using Capistrano to deploy a Rails application. I'm thinking of a situation where there were database changes, so I can't simply cap deploy because the migrations need to run before the code is updated. I realize there's a cap deploy:migrations, but that's a little more automatic than I'd like. I'd like to:
Push the new code to the releases directory, but not update the symlink or restart the application.
ssh into the server, run rake:db_abort_if_pending_migrations to confirm that the migrations I want to run are the only pending ones, then run rake db:migrate manually.
Complete the deploy, updating the symlink and restarting the application.
Is there any easy way to do this with the built-in Capistrano tasks, or would I need to write my own deployment steps to accomplish this?
I should mention too that I'm thinking of cases (like adding columns) where the migration can be run on a live database. For more destructive changes I realize I'd need to bring down the site with a maintenance page during the deploy.
Try:
cap deploy:update_code
Do what you described loging in to the server manually or via cap
shell
cap deploy:symlink deploy:restart
See cap -e deploy:update_code deploy:symlink deploy:restart deploy:shell for more information.
I hope this will be helpful to You.

Resources