Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crontab in Amazon Elastic Beanstalk

I am doing a cron tab in AWS - Elastic Beanstalk with Ruby on Rails 3, but I don't know what is wrong.

I have this code in my .ebextensions/default.config

container_commands:
  01remove_old_cron_jobs:
    command: "crontab -r || exit 0"
  02send_test_email:
    command: crontab */2 * * * * rake send_email:test
    leader_only: true

I receive this error:

Failed on instance with return code: 1 Output: Error occurred during build: Command 02send_test_email failed .

UPDATE 1

I tried next:

crontab.txt

*/2 * * * * rake send_email:test > /dev/null 2>&1

default.config

02_crontab:
  command: "cat .ebextensions/crontab.txt | crontab"
  leader_only: true

RESULT: No errors, but it does not work.

UPDATE 2

crontab.sh

crontab -l > /tmp/cronjob
#CRONJOB RULES
echo "*/2 * * * * /usr/bin/wget http://localhost/crontabs/send_test_email > /dev/null 2>&1" >> /tmp/cronjob
#echo "*/2 * * * * rake send_email:test > /dev/null 2>&1" >> /tmp/cronjob

crontab /tmp/cronjob
rm /tmp/cronjob
echo 'Script successful executed, crontab updated.'

default.config

02_crontab:
  command: "/bin/bash .ebextensions/crontab.sh"
  leader_only: true

RESULT: Works with url, but not with rake task.

like image 230
JorgeGS Avatar asked Nov 21 '13 09:11

JorgeGS


People also ask

What are cron jobs in AWS?

cron is a Chef resource that represents a cron job. When AWS OpsWorks Stacks runs the recipe on an instance, the associated provider handles the details of setting up the job. job_name is a user-defined name for the cron job, such as weekly report . hour / minute / weekday specify when the commands should run.

What does crontab command do?

The crontab command submits, edits, lists, or removes cron jobs. A cron job is a command run by the cron daemon at regularly scheduled intervals. To submit a cron job, specify the crontab command with the -e flag. The crontab command invokes an editing session that allows you to create a crontab file.


2 Answers

Updated for 2018

In order to get this to work on the latest version of Elastic Beanstalk, I added the following to my .ebextensions:

.ebextensions/0005_cron.config

files:
  "/etc/cron.d/mycron":
    mode: "000644"
    owner: root
    group: root
    content: |
      56 11 * * * root . /opt/elasticbeanstalk/support/envvars && cd /var/app/current && /opt/rubies/ruby-2.3.4/bin/bundle exec /opt/rubies/ruby-2.3.4/bin/rake send_email:test >> /var/app/current/log/cron.log 2>&1

commands:
  remove_old_cron:
    command: "rm -f /etc/cron.d/*.bak"

How I got there:

There are four main issues to confront when trying to cron a rake task in AWS EB:

  1. The first hurdle is making sure all of your EB and Rails environment variables are loaded. I beat my head against the wall a while on this one, but then I discovered this AWS forum post (login may be required). Running . /opt/elasticbeanstalk/support/envvars loads all of your environment variables.

  2. Then we need to make sure we cd into the current app directory using cd /var/app/current.

  3. Next we need to know where to find the bundle and rake executables. They are not installed in the normal bin directories, but are located in a directory specific to your ruby version. To find out where your executables are located, ssh into your EB server (eb ssh) and then type the following:

    $ cd /var/app/current
    $ which bundle
    /opt/rubies/ruby-2.3.4/bin/bundle
    $ which rake
    /opt/rubies/ruby-2.3.4/bin/rake
    

    You could probably guess the directory based on your ruby version, but the above commands will let you know for sure. Based on the above, your can build your rake command as:

    /opt/rubies/ruby-2.3.4/bin/bundle exec /opt/rubies/ruby-2.3.4/bin/rake send_email:test
    

    NOTE: If you update your ruby version, you will likely need to update your cron config as well. This is a little brittle. I'd recommend making a note in your README on this. Trust me, six months from now, you will forget.

  4. The fourth thing to consider is logging. I'd recommend logging to the same location as your other rails logs. We do this by tacking on >> /var/app/current/log/cron.log 2>&1 to the end of our command string.

Putting all of this together leads to a cron command string of:

. /opt/elasticbeanstalk/support/envvars && cd /var/app/current && /opt/rubies/ruby-2.3.4/bin/bundle exec /opt/rubies/ruby-2.3.4/bin/rake send_email:test >> /var/app/current/log/cron.log 2>&1

Finally, I referenced the latest AWS documentation to build an .ebextensions config file for my cron command. The result was the .ebextensions/0005_cron.config file displayed at the top of this answer.

like image 193
Tom Aranda Avatar answered Sep 21 '22 19:09

Tom Aranda


I am having the same issue. Though I figured out that the reason that rake task doesn't run correctly on eb is because of RACK_ENV, RAILS_ENV and BUNDLE_WITHOUT
Defaults of eb:

RACK_ENV: production
RAILS_ENV: production
BUNDLE_WITHOUT: test:development

When the cron runs rake task, it runs in development mode, and gives gem not found error, as gems grouped in development are not installed.

you can see this by changing your cron a bit
from:

*/2 * * * * rake send_email:test > /dev/null 2>&1

to:

*/2 * * * * cd /var/app/current/ && /usr/bin/bundle exec /usr/bin/rake send_email:test > /tmp/cron_log 2>&1

and then checking the /tmp/cron_log file
To know the location of bundle and rake, run

which bundle
which rake

I tried setting RAILS_ENV in command in cron, but that didn't work aswell
One quick fix is to set

BUNDLE_WITHOUT to null

EDIT:

Finally I got it to work,

.ebextensions/.config

files:
  "/tmp/cron_jobs" :
    mode: "000777"
    content: |
      1 10 * * * cd /var/app/current/ && RACK_ENV=production rake some:task >> /var/app/current/log/cron_log 2>&1
    encoding: plain
container_commands:
  01_delete_cron_jobs:
    command: "crontab -r -u webapp || exit 0"
  02_add_cron_jobs:
    command: "crontab /tmp/cron_jobs -u webapp"
    leader_only: true
option_settings:
  - option_name: RAILS_ENV
    value: production
  - option_name: RACK_ENV
    value: production

Notice the '-u webapp' when removing and adding cron, this will run this cron under user webapp. The above will also run in production mode. And the output will be dumped in log/cron_log file.

If the above wont work then adding 'Bundle exec' before 'rake some:task' might work.

like image 25
Salman Siddiqui Avatar answered Sep 23 '22 19:09

Salman Siddiqui