Capistrano, Whenever, Rails.
Using Whenever and Capistrano I pushed new data to the crontab on my server.
$ crontab -l
# Begin Whenever generated tasks for: myAPP
* * * * * /bin/bash -l -c 'cd /home/.../apps/myAPP/releases/20184..1433 && bin/rails runner -e production '\''myModel.new.HELLO()'\'''
# End Whenever generated tasks for: myAPP
myModel -> HELLO()
def HELLO()
p "HELLO"
end
How do I know if this is working? I don't think it is because the logs are blank. What am I doing wrong?
thanks
p "HELLO" just prints to stdout, which doesn't do much good in a cronjob context. Try this code instead:
def HELLO()
Rails.logger.info "HELLO"
end
This will print the message to the standard Rails log file. By default, this will be logs/production.log in the current release that Capistrano deployed.
Related
Im' trying to figure out how Whenever gem is working.
I would like to create a User instance every minute.
I put the following in my schedule.rb file :
set :output, "/log/cron_log.log"
set :environment, 'development'
every 1.minute do
rake "User.create!(nni: 'TEST0',
password: '123123',
password_confirmation: '123123',
nomprenom: 'user')"
end
Then I typed whenever --update-crontab and checked with crontab -l and get the following
# Begin Whenever generated tasks for: /home/harri/Documents/argia/config/schedule.rb at: 2018-07-10 17:19:18 +0200
* * * * * /bin/bash -l -c 'cd /home/harri/Documents/argia && RAILS_ENV=development bundle exec rake User.create!(nni: '\''TEST0'\'', password: '\''123123'\'', password_confirmation: '\''123123'\'', nomprenom: '\''user'\'') --silent >> /log/cron_log.log 2>&1'
# End Whenever generated tasks for: /home/harri/Documents/argia/config/schedule.rb at: 2018-07-10 17:19:18 +0200
Then I start my localhost and nothing happens, nothing in the log and it doesn't create any User instance.
I'm trying to figure out how Whenever gem is working.
It works by generating a crontab file with your commands. Then OS/crond take over.
Then I start my localhost and nothing happens, nothing in the log and it doesn't create any User instance.
Well, that's not a valid rake command you have there. Check cron logs, you'll see an error there. Did you mean to use runner?
I am using Whenever v0.9.7 with Rails 4.2.4. whenever is using development database in production also.
When i execute whenever i get following which shows production. But the time retrieved here is from development database and not production.
45 10 * * * /bin/bash -l -c 'cd /data/swati/Projects/metal && bundle exec bin/rails runner -e production '\''Mixins::UploadMaster.new.upload_data(ErpFile.find(4).table_name, ErpFile.find(4).file_name)'\'' >> /data/swati/Projects/metal/log/cron_log.log 2>&1'
Can anyone help resolve the issue?
Here is my schedule.rb
require File.expand_path('../environment', __FILE__)
set :output, ENV["CRON_LOG_FILE"]
erp_access = ErpAccess.first
erp_access.erp_files.each do |erp_file|
if erp_file.start_time
if erp_file.repeat_hours
every erp_file.repeat_hours.hours, at: erp_file.start_time do
toRun = 'Mixins::UploadMaster.new.upload_data(ErpFile.find(' + erp_file.id.to_s + ').table_name, ErpFile.find('+ erp_file.id.to_s + ').file_name)'
runner toRun
end
end
end
end
i follow all the steps for whenever with reference to https://github.com/javan/whenever
in schedule.rb
require 'yaml'
set :environment, 'production'
set :output, {
:error => "/log/error.log",
:standard => "/log/cron.log"
}
every 1.minute do
runner "User.weekly_update"
end
in gemfile
gem 'whenever', :require => false
output of some command
localhost:~/project$ whenever -i
[write] crontab file updated
localhost:~/project$ crontab -l
# Begin Whenever generated tasks for: /home/bacancy/project/config/schedule.rb
* * * * * /bin/bash -l -c 'cd /home/bacancy/project && script/rails runner -e production '\''User.weekly_update'\'' >> /log/cron.log 2>> /log/error.log'
# End Whenever generated tasks for: /home/bacancy/project/config/schedule.rb
# Begin Whenever generated tasks for: store
* * * * * /bin/bash -l -c 'cd /home/bacancy/project && script/rails runner -e development '\''User.weekly_update'\'''
# End Whenever generated tasks for: store
# Begin Whenever generated tasks for: lapulguilla
# End Whenever generated tasks for: lapulguilla
and then i type
localhost:~/project$ whenever
* * * * * /bin/bash -l -c 'cd /home/bacancy/project && script/rails runner -e production '\''User.weekly_update'\'' >> /log/cron.log 2>> /log/error.log'
## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.
In User model i have definition self.weekly_update
def self.weekly_update
puts "cronjobs is called in every minutes"
end
Your everything is correct, its just that you are saying to cron job to print something in background, so it is doing that and you are able to observe it.
Instead you should try create or destroy some records to feel the changes i think :)
I am using Whenever gem with rails. For some reason the first cronjob does not work. If i copy paste the command into the shell manually, it works as it should.
The second "touch testing123.txt" also works fine.
I have no idea why the GiftPackage.do_scheduled_deliveries rails method does not run. I'm really at a loss right now.. any help would be greatly appreciated!
# Begin Whenever generated tasks for: /var/www/mysite/releases/20130131200554/config/schedule.rb
*/1 * * * * /bin/bash -l -c 'cd /var/www/mysite/releases/20130131200554 && script/rails runner -e staging '\''GiftPackage.do_scheduled_deliveries'\'''
*/1 * * * * /bin/bash -l -c 'cd /var/www/mysite/releases/20130131200554 && touch testing123.txt'
# End Whenever generated tasks for: /var/www/mysite/releases/20130131200554/config/schedule.rb
Thanks!
:)
Most likely you are getting an error within the app itself.
First step would be, run the task in the console using the staging environment.
Second would be to check the cron logs and see if it is outputting any errors.
You can set whenever to log output by adding the following to your schedule.rb file;
set :output, "/[path to log]/cron.log"
This should help you get closer to finding the solution.
Try setting your PATH variable before the jobs, your cron is probably not able to find ruby :
For instance :
PATH=/usr/local/rvm/gems/ruby-1.9.3-p194/bin:/usr/local/rvm/gems/ruby-1.9.3-p194#global/bin:/usr/local/rvm/rubies/ruby-1.9.3-p194/bin:/usr/local/rvm/bin:/usr/local/sbin:/usr/local/$
# Begin Whenever generated tasks for: /var/www/mysite/releases/20130131200554/config/schedule.rb
*/1 * * * * /bin/bash -l -c 'cd /var/www/mysite/releases/20130131200554 && script/rails runner -e staging '\''GiftPackage.do_scheduled_deliveries'\'''
*/1 * * * * /bin/bash -l -c 'cd /var/www/mysite/releases/20130131200554 && touch testing123.txt'
# End Whenever generated tasks for: /var/www/mysite/releases/20130131200554/config/schedule.rb
I'm loving how capistrano has simplified my deployment workflow, but often times a pushed change will run into issues that I need to log into the server to troubleshoot via the console.
Is there a way to use capistrano or another remote administration tool to interact with the rails console on a server from your local terminal?
**Update:
cap shell seems promising, but it hangs when you try to start the console:
cap> cd /path/to/application/current
cap> pwd
** [out :: application.com] /path/to/application/current
cap> rails c production
** [out :: application.com] Loading production environment (Rails 3.0.0)
** [out :: application.com] Switch to inspect mode.
if you know a workaround for this, that'd be great
I found pretty nice solution based on https://github.com/codesnik/rails-recipes/blob/master/lib/rails-recipes/console.rb
desc "Remote console"
task :console, :roles => :app do
env = stage || "production"
server = find_servers(:roles => [:app]).first
run_with_tty server, %W( ./script/rails console #{env} )
end
desc "Remote dbconsole"
task :dbconsole, :roles => :app do
env = stage || "production"
server = find_servers(:roles => [:app]).first
run_with_tty server, %W( ./script/rails dbconsole #{env} )
end
def run_with_tty(server, cmd)
# looks like total pizdets
command = []
command += %W( ssh -t #{gateway} -l #{self[:gateway_user] || self[:user]} ) if self[:gateway]
command += %W( ssh -t )
command += %W( -p #{server.port}) if server.port
command += %W( -l #{user} #{server.host} )
command += %W( cd #{current_path} )
# have to escape this once if running via double ssh
command += [self[:gateway] ? '\&\&' : '&&']
command += Array(cmd)
system *command
end
This is how i do that without Capistrano: https://github.com/mcasimir/remoting (a deployment tool built on top of rake tasks). I've added a task to the README to open a remote console on the server:
# remote.rake
namespace :remote do
desc "Open rails console on server"
task :console do
require 'remoting/task'
remote('console', config.login, :interactive => true) do
cd config.dest
source '$HOME/.rvm/scripts/rvm'
bundle :exec, "rails c production"
end
end
end
Than i can run
$ rake remote:console
I really like the "just use the existing tools" approach displayed in this gist. It simply uses the SSH shell command instead of implementing an interactive SSH shell yourself, which may break any time irb changes it's default prompt, you need to switch users or any other crazy thing happens.
Not necessarily the best option, but I hacked the following together for this problem in our project:
task :remote_cmd do
cmd = fetch(:cmd)
puts `#{current_path}/script/console << EOF\r\n#{cmd}\r\n EOF`
end
To use it, I just use:
cap remote_cmd -s cmd="a = 1; b = 2; puts a+b"
(note: If you use Rails 3, you will have to change script/console above to rails console, however this has not been tested since I don't use Rails 3 on our project yet)
cap -T
cap invoke # Invoke a single command on the remote ser...
cap shell # Begin an interactive Capistrano session.
cap -e invoke
------------------------------------------------------------
cap invoke
------------------------------------------------------------
Invoke a single command on the remote servers. This is useful for performing
one-off commands that may not require a full task to be written for them. Simply
specify the command to execute via the COMMAND environment variable. To execute
the command only on certain roles, specify the ROLES environment variable as a
comma-delimited list of role names. Alternatively, you can specify the HOSTS
environment variable as a comma-delimited list of hostnames to execute the task
on those hosts, explicitly. Lastly, if you want to execute the command via sudo,
specify a non-empty value for the SUDO environment variable.
Sample usage:
$ cap COMMAND=uptime HOSTS=foo.capistano.test invoke
$ cap ROLES=app,web SUDO=1 COMMAND="tail -f /var/log/messages" invoke
The article http://errtheblog.com/posts/19-streaming-capistrano has a great solution for this. I just made a minor change so that it works in multiple server setup.
desc "open remote console (only on the last machine from the :app roles)"
task :console, :roles => :app do
server = find_servers_for_task(current_task).last
input = ''
run "cd #{current_path} && ./script/console #{rails_env}", :hosts => server.host do |channel, stream, data|
next if data.chomp == input.chomp || data.chomp == ''
print data
channel.send_data(input = $stdin.gets) if data =~ /^(>|\?)>/
end
end
the terminal you get is not really amazing though. If someone have some improvement that would make CTRL-D and CTRL-H or arrows working, please post it.