How to setup Whenever gem in production (RVM) - ruby

I've one rake task which i want to execute once every day:
in production installed rvm
in schedule.rb i have
set :output, "/home/username/data/public_html/log/cron_log.log"
every 24.hours do
rake "fetch:smth"
end
crontab -l shows me:
MAILTO="my.mail#gmail.com"
PATH="/usr/local/rvm/rubies/ruby-1.9.3-p125/bin/ruby "
#daily cd /home/username/data/www/nameofsite.com && RAILS_ENV=production bundle exec rake fetch:smth
truly, i'm a little bit confused, coz previously i didn't have experience with cron, so plz help.
EDIT #1
i've run rvm env -- path 1.9.3#global
and it gave me:
PATH="/usr/local/rvm/gems/ruby-1.9.3-p125/bin:/usr/local/rvm/gems/ruby-1.9.3-p125#global/bin:/usr/local/rvm/rubies/ruby-1.9.3-p125/bin:/usr/local/rvm/bin:$PATH"
and then i've
MAILTO="said.kaldybaev#gmail.com"
PATH="/usr/local/rvm/gems/ruby-1.9.3-p125/bin:/usr/local/rvm/gems/ruby-1.9.3-p125#global/bin:/usr/local/rvm/rubies/ruby-1.9.3-p125/bin:/usr/local/rvm/bin:$PATH"
#daily RAILS_ENV=production rake rate:fetch
and when i run execute, from ISPmanager, it gave me: Exited with return code = 1
the link below says that if the exit error is 1, then there is already a /var/run/cron.pid file. and it's true, but i don't have root privileges

You don't need schedule.rb if you're calling the task from cron. That's handled by the #daily entry in crontab. Just set the logfile name as an environment variable and have the rake task refer to that. You'll probably also need more in your $PATH than just the path to the ruby binary, otherwise bundle isn't going to be found. While you're giving the path to a ruby, you're not actually selecting it for RVM to know what you mean, so it's not going to be able to find the right gemset. RVM provides wrappers which Do The Right Thing for this sort of task - replace bundle exec with /usr/local/rvm/wrappers/ruby-1.9.3-p125 -S bundle exec and it should work.
Hope that gives you some ideas. There's more here.
UPDATE #1
With Edit #1, you've fixed one problem and created another. You still need to cd to the app directory, otherwise rake won't find the Rakefile.

Related

Ruby: 'bundle exec' throws error for all shell commands

In my project, I have a Gem that contains a shell script in its bin folder, let's call the script do_something.sh.
do_something.sh actually executes a ruby script using Jruby command, the script is called ruby_script.rb.
I am trying to call do_something.sh from my project using:
bundle exec do_something.sh
it keeps throwing errors for all shell commands in the script. I erased all the contents of the script and added only one line "echo 'Hello'" and it is still throwing the following error
NoMethodError: undefined method echo' for main:Object
/usr/local/rvm/gems/ruby-2.1.1#projectName/gems/gemName/bin/do_something.sh:10:in'
/usr/local/rvm/gems/ruby-2.1.1#projectName/bin/do_something.sh:23:in load'
/usr/local/rvm/gems/ruby-2.1.1#projectName/bin/do_something.sh:23:in'
Edit#1
All the files has execute permission.
I also tried to put ruby_script.rb in the bin directory where are files are executables (according to a rule in the gemspec file) and tried calling
bundle exec ruby_script.rb
I get the error "bundler: command not found: ruby_script.rb"
bundle exec ruby ruby_script.rb
I get the error "ruby: No such file or directory -- ruby_script.rb (LoadError)"
Why am I getting this error and how can I solve it? I want to be able to either run do_something.sh or ruby_script.rb. Right now, ruby_script.rb is not recognised and do_something.sh does not recognise the commands.
Ok, finally after two days, I was able to make it work.
bundle install installs my GEM and creates a ruby wrapper by default to sh files in the 'bin' directory. So, when I call my script using bundle exec the ruby wrapper gets called first and it calls my script using a ruby 'load' function. This load function expects a ruby file and that is why all my shell script in the file threw errors, because they were expected to be in ruby.
A workaround to this is installing my gem before 'bundle install' using the following command:
gem install --no-wrapper my-gem
Apparently this command disabled creating the ruby wrapper and I was finally able to call the script using bundle execute do_something.sh
Try specifying sh when you run bundle exec. The NoMethodError is from the script being executed in ruby and not sh.
bundle exec sh do_something.sh
In order to make it work. Setting_up_permissions_on_a_script
First: you have to change the mode for the file using chomd +x file_path
Second: Now you can call either by bundle exec file_path or ./file_path
N.B
1: Don't forget to add #!/bin/sh on top of the file.
2: And do check with deploy-a-shell-script-with-ruby-gem-and-install-in-bin-directory will definitely help you.
Hope this help you!
According to Rubygems Specification Reference, executables included in the gem
... must be executable Ruby files. Files that use bash or other interpreters will not work.
In order to to add an executable to a gem please make sure to read the Adding an executable section on Rubygems Guide.
Eventually you'll be able to run the executable like this:
bundle exec do_something
where bundle exec part is optional.

Why does Capistrano run a command differently

I have been noticing some weird stuff with Capistrano lately. But before I can explain that let me provide some head on from where it is exactly coming from.
As a part of updating my crontab on every deployment. I decided to use whenever/capistrano recipe.
But for some reason(not known to me but I see a issue in github describing the same). Every time I attempt to do so I see following error.
"database configuration does not specify adapter"
Important bit. here how the command look like
INFO [a558a04a] Running ~/.rvm/bin/rvm 2.2.2#thrasher do bundle exec whenever --update-crontab thrasher --set environment=production --roles=app,web,db as deploy#x.x.x.x
DEBUG [a558a04a] Command: cd /home/deploy/project-scp/thrasher/releases/20160129130817 && ~/.rvm/bin/rvm 2.2.2#thrasher do bundle exec whenever --update-crontab thrasher --set environment=production --roles=app,web,db
DEBUG [a558a04a] scheduling frequent upload job
scheduling daily upload job
DEBUG [a558a04a] [write] crontab file updated
INFO [a558a04a] Finished in 2.411 seconds with exit status 0 (successful).
Kindly, take a note of the command.
~/.rvm/bin/rvm 2.2.2#thrasher do bundle exec whenever ...
Now, in order to solve this problem. I set the whenever_command, a capistrano variable to look like this.
set :whenever_command,["RAILS_ENV=#{fetch(:stage)",:bundle,:exec,:whenever]
And ...
When I ran the capistrano again, I saw this.
Running /usr/bin/env RAILS=production bundle exec whenever --update-crontab thrasher --set environment=production --roles=app,web,db as deploy#x.x.x.x
DEBUG [b67e3351] Command: cd /home/deploy/project-scp/thrasher/releases/20160129131301 && /usr/bin/env RAILS=production bundle exec whenever --update-crontab thrasher --set environment=production --roles=app,web,db
Command Executed was
/usr/bin/env RAILS=production bundle exec whenever ...
Question:
Why did the 2 time the command did not look like this.
~/.rvm/bin/rvm 2.2.2#thrasher do RAILS_ENV=production bundle exec whenever
Note:
Rails 4.0.4
Capistrano Version: 3.4.0 (Rake Version: 10.5.0)
Ruby ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
Also using
capistrano/rvm
Update:
In accordance with #will_in_wi answer. To solve the whenever issue I also tried doing this.(inside deploy.rb file.)
namespace :deploy do
...
...
before "whenever:update_crontab", "deploy:set_rails_env"
end
Short answer: Placing an environment variable inside the :whenever_command is not the right way to do it. Based on the whenever/capistrano code, you should use :whenever_command_environment_variables.
Remove your :whenever_command and try this instead:
set :whenever_command_environment_variables, -> { { :rails_env => fetch(:stage) } }
Long answer: you are using capistrano/rvm, which does some magic with Capistrano's "command map" to automatically prefix certain commands with ~/.rvm/bin/rvm.... One of those certain commands is bundle, for example. If you change the whenever command to no longer start with :bundle, the mapping will no longer work.
Without seeing your Capfile, you might need to enable some subset of capistrano/rails. That is what will force RAILS_ENV to be set: https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/set_rails_env.rake

How do I run Rails/Rake from another directory?

Without cd-ing into the root directory of my Rails application, how can I execute a Rails or Rake command for that application.
I tried:
bundle exec rake my_tasks:do_stuff BUNDLE_GEMFILE=/PATH/TO/RAILS_APP/Gemfile
among other combinations, to no avail.
[Update]
The issue is actually two-fold, bundle doesn't know where the gemfile is and rake doesn't know what to run.
To use Bundler:
BUNDLE_GEMFILE=/PATH/TO/RAILS_APP/Gemfile bundle exec ...
Note that BUNDLE_GEMFILE has to go before 'bundle exec'.
To use Rake:
rake -f /PATH/TO/RAILS_APP/Rakefile my_task:do_stuff
To use Rails console:
????
Have yet to figure out how to enter the Rails console from another directory. Looking at the source, I think it may not be possible, because it eventually does File.join('script','rails') to kick off the rails process.
Without you showing the error message you are getting, I'm assuming it has less to do with Bundler than it does Rake. When the rake command is run, it searches for a Rakefile starting in the current directory and traversing up the tree until it finds one. You can override this behavior by explicitly specifying a Rakefile in the options to the rake command. This is done using the -f <RAKEFILE> option.
eg.
bundle exec rake -f /PATH/TO/RAILS_APP/Rakefile my_task:do_stuff
Bear in mind that your Rake tasks have to be "CWD agnostic". Most tasks and scripts are as they tend to get the project directory based on a path relative to a known file in the directory tree. You probably already understand that, but it's worth mentioning in case the tasks are expecting the current working directory to actually be the rails root. That would be a case where running them from outside the project could potentially be dangerous.

bundle exec thin start vs ./bundle/bin/thin start

I'm trying to understand how bundle exec works and what it does. I've installed the gems using bundle install like so:
bundle install --binstubs ./bundle/bin --path ./bundle/lib'
This creates a script ./bundle/bin/thin that I can use to start my Rails application using thin like so:
./bundle/bin/thin start -p 8080
However I see most articles on the internet recommend starting thin using bundle exec like this:
bundle exec thin start -p 8080
What is the difference between the two? My tests show that bundle exec doesn't call the ./bundle/bin/thin script, so how does bundle exec differ from the script?
There's no significant difference: they're two ways to accomplish the same thing, which is to run the correct version of the command for your bundle, with the environment set up to ensure that other bundled gens can be loaded by the command. The choice comes down to a matter of convenience.
The benefit of bundle exec is that you don't need to generate binstubs to use it: it just works with the existing Gemfile. This explains why you don't see it invoking the binstub you do have.
Some people don't like having to type bundle exec before every command, so the goal with binstubs is that you can add the directory to the front of your PATH and call the command normally. The drawback is that there is a potential security or usability concern if a bundled gem contains a command that shadows an important system command (e.g., ls).
If you don't put it in your PATH and always call it as bundle/bin/thin, you don't have the security concern, but it also gives you no particular benefit over using bundle exec thin.
In that specific case, there is no difference. bundle exec thin start -p 8080 will end up calling .bundle/bin/thin, but what if you you installed binstubs in a different path? bundle exec thin start will read your .bundle/config to find where your binstubs folder is. If you don't have binstubs installed and say you have 3 versions of thin installed, bundle exec will execute the one that's defined in your Gemfile.
Edit: #tadman also made a good point that I initially missed. When you use bundle exec, the gem environment from your Gemfile will be used, without it, it'll load the latest version of each gem currently installed.
The bundle exec method is the "official" way to do it. If you want to make use of the --binstubs feature, which is unusual, you can.
Remember that ./bundle/bin/thin is not the script, but a wrapper or "stub" that calls the script with the proper bundle exec environment loaded.

How to build and run a Ruby command-line tool found on github?

Hi cloned a simple app ( https://github.com/cfx/twix) on github that allows me to send Twitter messages from the console, but I'm not sure how to run it.
I now have a folder in my users/name director called Twix. Inside twix, I have these folders created by the app.
README Rakefile bin lib test
The readme doesn't provide a lot of instruction to get things started. It just tells you what to do after the program's running (see below).
Questions: What command do I use to get this started? What folder do I need to be in?
The README
Twix 0.0.1
Simple twitter client for console
Keys:
q - quit
t - write new message
If you want to post your twit, finish you message with !SEND
If you want abort and back to your feed, finish your message with !EXIT
new features soon
This program is packaged as a gem. The following command will install the gem (run it in the Twix directory):
rake package && gem install pkg/twix-0.0.1.gem
You can now run the program from anywhere with the twix command.
Edit
The first thing I saw in the repository was the Rakefile, meaning there were some rake tasks defined. When you find yourself in this case, running rake -T is your best bet as it will show you the rake tasks available. Its output was the following:
(in /home/benoit/code/clones/twix)
rake clobber_package # Remove package products
rake gem # Build the gem file twix-0.0.1.gem
rake package # Build all the packages
rake repackage # Force a rebuild of the package files
I picked the command that would be the most likely to build the gem: the package one. I guess the gem task would have worked as well.
Running rake package gave me the following output:
(in /home/benoit/code/clones/twix)
mkdir -p pkg
WARNING: no homepage specified
Successfully built RubyGem
Name: twix
Version: 0.0.1
File: twix-0.0.1.gem
mv twix-0.0.1.gem pkg/twix-0.0.1.gem
All that was left was to install the pkg/twix-0.0.1.gem created by the previous command:
gem install pkg/twix-0.0.1.gem
There's another case you could have encountered: the presence of a twix.gemspec in the root directory of the application. In this case, running:
gem build twix.gemspec
would have built the gem, the installation step remains the same.
ruby ./bin/twix
or
ruby -I lib ./bin/twix

Resources