开发者

Need to set up rvm environment prior to every cron job

I installed and configured RVM roughly following the pattern outlined in the first part of this set of instructions: http://blog.ninjahideout.com/posts/a-guide-to-a-nginx-passenger-and-rvm-server

Basically, this means there is no pre-build system ruby (all ruby installs are RVM-managed) and RVM is installed system-wide instead of attached to a particular user (files at /usr/local/rvm) so all users in the rvm group can access the same rubies with the same installed gems.

One issue with setting up the system this way is that the rvm environment must be set up in a shell session before ruby can be used. For all rvm users, I put this in their .bashrc: source "/usr/local/rvm/scripts/rvm". This works fine for ssh sessions.

The problem comes in play for cron jobs, which don't execute .bashrc. The rvm script a开发者_StackOverflow社区bove (/usr/local/rvm/scripts/rvm) is considerably more complicated than setting up a few environment variables, so I'd actually like to run this command prior to every job in the file.

Sure, I could do that manually, like so:

1 2 * * * source "/usr/local/rvm/scripts/rvm"; /do/some/cron/job/1
3 4 * * * source "/usr/local/rvm/scripts/rvm"; /do/some/cron/job/2
5 6 * * * source "/usr/local/rvm/scripts/rvm"; /do/some/cron/job/3
7 8 * * * source "/usr/local/rvm/scripts/rvm"; /do/some/cron/job/4

But I'd prefer to do something like this:

[execute] source "/usr/local/rvm/scripts/rvm"

1 2 * * * /do/some/cron/job/1
3 4 * * * /do/some/cron/job/2
5 6 * * * /do/some/cron/job/3
7 8 * * * /do/some/cron/job/4

Obviously, the above syntax doesn't work. But, is there some way to get this to work? The cron man pages and documentation were not of much help here. But is there some trick or standard way to achieve this?

If it matters, I'm running Ubuntu 10.10 (Maverick Meerkat).


Just do rvm cron setup

This lets rvm setup ruby cron settings. As a result the crontab gets populated with environment variable assignments.

Then crontab -e

Add your cron tasks (below the assignments), save and close and you are good to go!!


You don't need to write wrappers (following that logic, you might as well write a wrapper to the wrapper). Please keep things simple. All you need to do is configure your cron job to launch a bash shell, and make that bash shell load your environment.

The shebang line in your script should not refer directly to a ruby executable, but to rvm's ruby:

#!/usr/bin/env ruby

This instructs the script to load the environment and run ruby as we would on the command line with rvm loaded.

On many UNIX derived systems, crontabs can have a configuration section before the actual lines that define the jobs to be run. If this is the case, you would then specify:

SHELL=/path/to/bash  

This will ensure that the cron job will be spawned from bash. Still, your environment is missing, so to instruct bash to load your environment, you will want to add to the configuration section the following:

BASH_ENV=/path/to/environment (typically .bash_profile or .bashrc) 

HOME is automatically derived from the /etc/passwd line of the crontab owner, but you can override it.

HOME=/path/to/home

After this, a cron job might look like this:

15 14 1 * *     $HOME/rvm_script.rb

What if your crontab doesn't support the configuration section? Well, you will have to give all the environment directives in one line, with the job itself. For example,

15 14 1 * * export BASH_ENV=/path/to/environment && /full/path/to/bash -c '/full/path/to/rvm_script.rb'

Full blog post on the subject


Crontab files generally only allow two types of things (plus comments and blank lines if you want to be pedantic):

  1. Environment variable setting.
  2. Command specifications.

And some crontabs don't even support setting environment variables (although I doubt you'll come across such a thing practice).

If you need to do more than set some environment variables then you're going to need to put your source "/usr/local/rvm/scripts/rvm" either in the cron specs as you have in your question or you'll need to wrap your cron jobs in a cron runner something like this:

#!/bin/sh
source "/usr/local/rvm/scripts/rvm"
exec $1

And then in the crontab:

1 2 * * * /path/rvm_cron_runner /do/some/cron/job/1

Six of one, half a dozen of the other.


If your cronjob is a straight ruby file, the docs say you can just use the built-in wrapper which will load up the correct ruby version and gemset:

1 0  * * * /usr/local/rvm/bin/ruby-1.9.2-p290@projectX /path/to/script.rb

You would still need to add this call to each line however.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜