35

I'm trying to run a Ruby script using rbenv with cron. I know that I need to load rbenv in order to have the right Ruby version loaded.

I've tried options like this:

*/10 * * * * /bin/bash -c 'source $HOME/.bashrc; cd /data/app; ruby -v' >> /tmp/logfile.txt 2>&1

but as the session is not interactive, I'm not having the right Ruby version. I've found example like this:

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

It didn't work neither. Then I wrote a loader, which only load rbenv in the current shell but it doesn't work.

*/1 * * * * /bin/bash -c '$HOME/.rbenv/loader.sh ; cd /data/app/; ruby -v ' >> /tmp/logfile.txt 2>&1

Now I'm searching for another way to load it ... any ideas?

Sajad Torkamani
  • 544
  • 1
  • 7
  • 18
kmmndr
  • 884
  • 1
  • 7
  • 8

5 Answers5

48

I've found a solution to load rbenv. Either with a loader importing rbenv to the PATH :

*/1 * * * * /bin/bash -c '. $HOME/.rbenv/loader.sh ; cd /data/app/; ruby -v'

The '.' before '$HOME/.rbenv/loader.sh' is important, it runs the script in the current shell

Or without loader, which is better :

*/1 * * * * /bin/bash -c 'export PATH="$HOME/.rbenv/bin:$PATH" ; eval "$(rbenv init -)"; cd /data/app/; ruby -v'

kmmndr
  • 884
  • 1
  • 7
  • 8
  • 5
    Note that your loader only needs to contain the `$PATH` changes: `export PATH=$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH`. And you don't even have to cd, just run `ruby /data/app/script_name.rb` and rbenv will find the correct version. You can omit the shims path if you don't need it, as you already know. – Kelvin Feb 26 '13 at 23:46
  • `* * * * * * /bin/bash -c '. /etc/profile.d/rbenv.sh; ruby -v'` for system wide rbenv installations and users without shell / home dir – scones Sep 08 '16 at 13:57
  • You can set PATH in your whole crontab not just for a specific entry. https://stackoverflow.com/a/2409369/629057 – John Kloian Apr 16 '18 at 20:13
20

A better solution is to simply use the command bash -lc command. This will read your bash profile file, which would setup rbenv. From the bash man page:

-l Make bash act as if it had been invoked as a login shell

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

John K. Chow
  • 1,651
  • 16
  • 24
  • 5
    I don't recommend this, because it can potentially add a lot of overhead if `.bash_profile`, etc does stuff that only an interactive shell needs. You might even cause trouble if you've aliased certain bash commands. – Kelvin Feb 26 '13 at 23:51
  • maybe this will help http://www.eq8.eu/blogs/15-cron-rbenv-bundle-exec-rake-task `* * * * * PATH=$PATH:/usr/local/bin && bash -lc "cd /home/deploy/apps/myapp && RACK_ENV=production bundle exec rake event:process ` – equivalent8 Jul 02 '15 at 15:46
  • @EstebanFeldman Make sure that 'eval "$(rbenv init -)"' is in your .bashrc and that .bashrc is loaded from .bash_profile. – Shelvacu Mar 15 '16 at 21:58
  • This makes the silent assumption, that the cron job user actually has a home dir. – scones Sep 08 '16 at 13:47
5

Even though kmmndr's answer is correct, I also like the bash -l-approach.

Opening a non-interactive login shell keeps things simpler and since my Rails applications and Ruby scripts all run under the same user, overhead is not a problem.

So instead of

*/1 * * * * /bin/bash -c 'export PATH="$HOME/.rbenv/bin:$PATH" ; eval "$(rbenv init -)"; cd /data/app/; ruby -v'

I do

*/1 * * * * /bin/bash -lc 'cd /data/app/; ruby -v'

As noted in the above answer, bash -l will act as if you login normally, which means that your rbenv environment will already be set up (as long as you have the appropriate lines in your .bashrc, .bash_profile of /etc/profile.d/*).

If you need more detail, I wrote a blog post about this topic.

Michael Trojanek
  • 1,813
  • 17
  • 15
4

This answer from @Kelvin worked for me:

*/1 * * * * PATH=$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH ruby -v >> ~/test.out
Ardee Aram
  • 4,740
  • 8
  • 36
  • 37
2

For my backup script in Ruby I simply use ~/.rbenv/bin/rbenv exec ruby [options] /path/to/ruby/script.rb. Try this:

* * * * * ~/.rbenv/bin/rbenv exec ruby -v > ~/rbenv-ruby-version.txt
rosenfeld
  • 1,730
  • 15
  • 19
  • And you ran it once a minute, every single minute of every day. You probably wanted `0 * * * *`, so that it runs once an hour. – VxJasonxV Aug 21 '20 at 08:32
  • This was set up so that I could test if the correct Ruby was running as soon as possible. Once confirmed I removed that line. It's not really a job I want to keep running in the server. The actual back-up command is another one. – rosenfeld Aug 21 '20 at 20:21