Setting path for whenever in cron so it can find ruby - ruby

My ruby is in /usr/local/bin. whenever can't find it, and setting PATH at the top of my cron file doesn't work either, I think because whenever is running the command inside of a new bash instance.
# this does not work
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin
# Begin Whenever generated tasks for: foo
0 * * * * /bin/bash -l -c 'cd /srv/foo/releases/20110429110637 && script/rails runner -e production '\''ActiveRecord::SessionStore::Session.destroy_recent(15)'\'''
# End Whenever generated tasks for: foo
How can I tell whenever where my ruby binary is? Making a symbolic link from /usr/bin seems messy to me, but I guess that might be the only option.
This question offers env :PATH, "..." in schedule.rb as a solution, but (a) I can't find any documentation of that feature anywhere in the docs (b) it doesn't seem to have solved the asker's problem (unfortunately it takes non-trivial turnaround time for me to just try it).
update actually it is in the bottom of this page, i'll try it now.
more info
I can't modify the cron command because it's generated by whenever
i verified that if I make a new bash shell with bash -l, /usr/bin/env finds ruby just fine
I just tried the exact command in cron, starting with /bin/bash, from the command line of that user, and it worked.
so, this is very mysterious...

The solution is to put this in schedule.rb:
env :PATH, ENV['PATH']
Here's a little guide I put together on the topic.

rewrite your crontab as
0 * * * * { PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin ; export PATH ;/bin/bash -l -c 'cd /srv/foo/releases/20110429110637 && script/rails runner -e production '\''ActiveRecord::SessionStore::Session.destroy_recent(15)'\''' ; }
Or you should try to figure out why your BASH shell is not picking the PATH=... that is almost certainly in your .profile or .bash_profile.
I hope this helps.

As John Bachir pointed out, you can do it via env. But let me add more input. I am deploying on AWS Opsworks. Unfortunately they do not have a ruby manager (RVM, Rbenv, etc) installed by default.
The first thing I needed to do was SSH into the instance and figure out which ruby I was using. This was easy enough by executing the which ruby command in a terminal.
$ which ruby
/usr/local/bin/ruby
Cron was using ruby located at /usr/bin/ruby. This needed to be changed.
In schedule.rb, I have:
set :env_path, ''
env :PATH, #env_path if #env_path.present?
In local, env_path doesn't need to be set. For most users, the only thing to do is execute whenever as such:
bundle exec whenever --set 'environment=development' --update-crontab
On a staging / production environment, ruby may be installed elsewhere. So running this may be more appropriate:
bundle exec whenever --set 'environment=staging&env_path=/usr/bin/local' --update-crontab
You will need to replace /usr/bin/local with the output of echo $PATH.
In Opsworks, however, I needed to create a custom Chef recipe that looked like:
node[:deploy].each do |application, deploy|
execute 'whenever' do
user 'deploy'
group 'nginx'
cwd "#{deploy[:deploy_to]}/current"
command "bundle exec whenever --set 'environment=#{deploy[:environment_variables][:RAILS_ENV]}&env_path=#{ENV['PATH']}' --update-crontab"
end
end
I hope the information here is clear enough.

Related

Update of blog site via cron does not work

Currently i have blog site which works with Octopress in relationship with Git but currently facing a problm that i can't update the site automatically via a cron triggered script. I'm using a script (update.sh) with the following contents:
#!/bin/bash -x
export PATH=/usr/local/rvm/gems/ruby-2.0.0-p247#global/bin/:/usr/local/rvm/bin/rvm:$PATH
cd /usr/local/repositories
cd supose.git
git fetch -q --all
cd /usr/local/vhost/octopress
git pull
rake generate
/usr/local/rvm/gems/ruby-2.0.0-p247/bin/jekyll generate
But i alway get the following error message:
+ rake generate
## Generating Site with Jekyll
+ /usr/local/rvm/gems/ruby-2.0.0-p247/bin/jekyll generate
invalid command. Use --help for more information
I know there must be a relationship with the environment, but i can't get the point to get it running.
If i login into the machine and cd into the folder and do rake generat it works like a charm.
Check the PATH you have when you login against the one crontab gives you. It may be quite different. rvm does other things as well as set the path. You'll need to make sure our PATH is correct, and run the script that rvm puts in your login profile [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm". You could try running . ~/.bash_profile ; (path_to_script)/update.sh as the crontab command.
instead of changing PATH use a wrapper - this will provide environment for your ruby:
rvm wrapper ruby-2.0.0-p247 --no-links rake jekyll
and then use it like this:
/usr/local/rvm/wrappers/ruby-2.0.0-p247/rake generate
/usr/local/rvm/wrappers/ruby-2.0.0-p247/jekyll generate

Cron job can't load gem

I have a ruby script that connects to an Amazon S3 bucket and downloads the latest production backup. I have tested the script (which is very simple) and it works fine.
However, when I schedule this script to be run as a cron job it seems to fail when it loads the Amazon (aws-s3) gem.
The first few lines of my script looks like this:
#!/usr/bin/env ruby
require 'aws/s3'
As I said, when I run this script manually, it works fine. When I run it via a scheduled cron job, it fails when it tries to load the gem:
`require': no such file to load -- aws/s3 (LoadError)
The crontab for this script looks like this:
0 3 * * * ~/Downloader/download.rb > ~/Downloader/output.log 2>&1
I originally thought it might be because cron is running as a different user, but when I do a 'whoami' at the start of my ruby script it tells me it's running as the same user I always use.
I have also done a bundle init and added the gem to my gemfile, but this doesn't seem to have any affect.
Why does cron fail to load the gem? I am running Ubuntu.
As mentioned here https://coderwall.com/p/vhv8aw you can simply try
rvm cron setup # let RMV do your cron settings
Make sure that you make copy of your crontab before running this command
If you're running it manually and it works you're probably in a different shell environment than cron is executing in. Since you mention you're on Ubuntu, the cron jobs probably execute under /bin/sh, and you're manually running them under /bin/bash if you haven't changed anything.
You can debug your environment problems or you can change the shell that your job runs under.
To debug, There are several ways to figure out what shell your cron jobs are using. It can be defined in
/etc/crontab
or you can make a cron job to dump your shell and environment information, as has been mentioned in this SO answer: How to simulate the environment cron executes a script with?
To switch to that shell and see the actual errors causing your job to fail, do
sudo su
env -i <path to shell> (e.g. /bin/sh)
Then running your script you should see what the errors are and be able to fix them (rubygems?).
Option 2 is to switch shells. You can always try something like:
0 3 * * * /bin/bash -c '~/Downloader/download.rb > ~/Downloader/output.log 2>&1'
To force your job into bash. That might also clear things up.
You may also explicitly set your Gem path:
GEM_HOME="/usr/local/rvm/gems/ruby-1.9.2-p290#my-special-gemset"
in a non cron environment execute echo $PATH, copy the path and paste it into your crontab, before your command:
echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin
and inside crontab:
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin
0 3 * * * ~/Downloader/download.rb > ~/Downloader/output.log 2>&1
Add this at the beginning of your cron
PATH="/home/user/.rvm/gems/ruby-2.1.4/bin:/home/user/.rvm/gems/ruby-2.1.4#global/bin:/home/user/.rvm/rubies/ruby-2.1.4/bin:/home/user/.rvm/gems/ruby-2.1.4/bin:/home/user/.rvm/gems/ruby-2.1.4#global/bin:/home/user/.rvm/rubies/ruby-2.1.4/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/home/user/.rvm/bin:/usr/local/sbin:/usr/sbin:/home/user/.rvm/bin:/home/user/.local/bin:/home/user/bin"
GEM_HOME='/home/user/.rvm/gems/ruby-2.1.4'
GEM_PATH='/home/user/.rvm/gems/ruby-2.1.4:/home/user/.rvm/gems/ruby-2.1.4#global'
MY_RUBY_HOME='/home/user/.rvm/rubies/ruby-2.1.4'
IRBRC='/home/user/.rvm/rubies/ruby-2.1.4/.irbrc'
RUBY_VERSION='ruby-2.1.4'
I've tried all the solution above, none of them worked until I tried;
0 12 * * * /bin/bash -l -c 'ruby /Users/simon/Desktop/script.rb'

Can the whenever gem preserve existing lines in a crontab file?

I am using:
Ruby 1.9.2
whenever 0.7.2
capistrano 2.9.0
capistrano-ext 1.2.1
I am using whenever in conjunction with Capistrano on deploys to manage my crontab files.
I noticed that it completely rewrites my crontab files each time.
I'd like to be able to set environment variables in cron to control PATH and MAILTO settings, which are regular cron environment variables.
Is there a way to make whenever not overwrite the entire crontab file, so that I can add customizations to my crontab file and be sure that they will persist?
Yes, you can do this. You'll just need to assign an identifier to the task being written to crontab:
whenever --update-crontab some_identifier_name
It will generate an entry in crontab like this:
# Begin Whenever generated tasks for: some_identifier_name
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /bin/bash -l -c 'cd /var/www/test/releases/20120416183153 && script/rails runner -e production '\''Model.some_method'\'' >> /tmp/cron_log.log 2>&1'
# End Whenever generated tasks for: some_identifier_name
Then whenever you call the command above it will only update where it finds the identifier you specified.

Monit + RVM + Thin on OSX / Linux

After trying for hours (and also trying God and Bluepill) I decided to ask my question here because I am completely clueless how to solve this issue.
I have a Rails app. I want to use Thin as my app server. I want to use Monit to monitor my Thin instances. I use RVM to manage my Ruby versions as my local user.
I have the following monit file set up that would assumably do what I want it to do, but doesn't:
check process thin-81
with pidfile /Users/Michael/Desktop/myapp/tmp/pids/thin.81.pid
start program = "/Users/Michael/.rvm/gems/ruby-1.9.2-p180/bin/thin start -c /Users/Michael/Desktop/myapp -e production -p 81 -d -P tmp/pids/thin.81.pid"
stop program = "/Users/Michael/.rvm/gems/ruby-1.9.2-p180/bin/thin stop -c /Users/Michael/Desktop/myapp -P tmp/pids/thin.81.pid"
if totalmem is greater than 150.0 MB for 2 cycles then restart
If I simply copy/paste the start program in to the command line (outside of Monit) it works. Same goes for the stop program to afterwards stop the Thin instance. Running it via Monit however, does not seem to work.
Running it in -v verbose mode yields the following:
monit: pidfile '/Users/Michael/Desktop/myapp/tmp/pids/thin.81.pid' does not exist
Which leads me to believe that Thin never initializes. Does Monit run as root or something? Cause if it does then it obviously won't have the correct gems installed since I'm using RVM and not the "system" Ruby. I am currently on OSX (but will deploy to Linux eventually) - does anyone know what the cause of this might be? And if Monit is run via root, how could I make it use RVM regardless? Or could I tell Monit to execute the start/stop programs as Michael:staff (I assume it would be on OSX?)
Any help is much appreciated!
monit clears out the environment and also doesn't run a shell for your command (let alone an interactive one). I find I have to do something like:
/usr/bin/bash -c 'export rvm_path=/home/foo/.rvm; . $rvm_path/scripts/rvm; cd my_ruby_app_path; $rvm_path/bin/rvm rvmrc load; ./my_ruby_app'
as the monit start command.
another option which I found in the RVM google group is as follows:
start program = "/bin/su - myuser -c '/path/to/myscript.rb start' "
su - user runs the user's shell as a login shell, so if the
user's shell is bash, it will cause ~/.bash_profile to be run so the
environment variables should be the same as just after that user
logged in.
We need the path for su, otherwise, monitrc would not able to find the su executable.
A better way would be to use an RVM wrapper to create a custom executable for thin. It will create the correct environment variables to use the right ruby and gems, and then launch thin. Read more about it using it with god here : https://rvm.io/integration/god/. It should work the same with monit
To create the wrapper:
rvm wrapper ruby#gemset bootup thin
Then change start program and stop program to use the executable you just created.

Cron Ubuntu does not fire ruby method

crontab -l gives me this
0,2,4,6,8,10 * * * * /bin/bash -l -c 'cd /home/ruben/Monitoring ; script/rails runner Ping.check_pings'
Why does this not work?
If i try "cd /home/ruben/Monitoring ; script/rails runner Ping.check_pings" in the command line it works. I have also tried it with "&&" as ";"
The problem may be related to PATH, or to some other environment variable (like GEM_HOME), that is defined properly in your command-line environment, but not in cron's environment.
crontab doesn't run with the enviroment of the user, rather it creates it's own slimmed down enviroment. This includes very small PATH - /usr/bin:/usr/sbin:. and some other variables. See more here - http://adminschoice.com/crontab-quick-reference
Easiest solution is to add '. ~/.profile' before you run rails, or to fix path in some other way.
BTW, before you try to add PATH=/my/path/here;$PATH into crontab - that syntax (variable expansion) is not allowed either

Resources