2

Apologies if this is a duplicate - there are a few results with similar questions but most of the answers are quite dated and I am having trouble getting it to work.

I am using the whenever gem to run a single task every hour in my rails app but I can't seem to get AWS to configure the Cron settings right.

My first thought was to SSH into the instance and run the whenever update /write command which went through fine but my task didn't run.

After reviewing the old questions on here I created a an ebextensions folder with a config file to run the update command but still no joy. I used this config script but don't really understand it so I assume I have not set it up right - can someone please assist?

files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_update_cron.sh"
mode: "000755"
owner: root
group: root
content: |
#! /usr/bin/env bash
. /opt/elasticbeanstalk/containerfiles/envvars
su -c "cd $EB_CONFIG_APP_CURRENT; bundle exec whenever --update-cron" 
- $EB_CONFIG_APP_USER

EDIT Added Logs

2018-01-09T23:24:45.282Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AppDeployStage1/AppDeployPostHook] : Starting activity...
[2018-01-09T23:24:45.282Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AppDeployStage1/AppDeployPostHook/01_cron.sh] : Starting 
activity...
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AppDeployStage1/AppDeployPostHook/01_cron.sh] : Completed 
activity. Result:
[write] crontab file updated
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AppDeployStage1/AppDeployPostHook] : Completed activity. 
Result:
Successfully execute hooks in directory 
/opt/elasticbeanstalk/hooks/appdeploy/post.
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AppDeployStage1] : Completed activity. Result:
Application version switch - Command CMD-AppDeploy stage 1 completed
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter] : Starting activity...
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter/ConfigLogRotation] : Starting activity...
[2018-01-09T23:24:46.618Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter/ConfigLogRotation/10-config.sh] : Starting 
activity...
[2018-01-09T23:24:46.778Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter/ConfigLogRotation/10-config.sh] : Completed 
activity. Result:
Disabled forced hourly log rotation.
[2018-01-09T23:24:46.779Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter/ConfigLogRotation] : Completed activity. 
Result:
Successfully execute hooks in directory 
/opt/elasticbeanstalk/addons/logpublish/hooks/config.
[2018-01-09T23:24:46.779Z] INFO  [1641]  - [Application update app-5c64-
180109_162309@15/AddonsAfter] : Completed activity.
[2018-01-09T23:24:46.779Z] INFO  [1641]  - [Application update app-5c64-

EDIT 2 my new config code that now forms the following errors:

commands:
 70.1-create-post-dir:
  # "mkdir -p" ignores error if directory already exists
  command: "mkdir -p /opt/elasticbeanstalk/hooks/appdeploy/post"

files:
 "/opt/elasticbeanstalk/hooks/appdeploy/post/01_cron.sh":
 mode: "000755"
 owner: root
 group: root
 content: |
  #!/usr/bin/env bash

  # Load environment data
  EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
  EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir) 
  EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
  EB_APP_DEPLOY_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
  # Export EB_APP_LOG_DIR so we can access it when running "whenever" below,
  # which accesses config/schedule.rb, which uses EB_APP_LOG_DIR.
  export EB_APP_LOG_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_log_dir)

  # Make sure the cron-whenever.log exists and is owned by $EB_APP_USER
  touch $EB_APP_LOG_DIR/cron-whenever.log
  chown $EB_APP_USER:$EB_APP_USER $EB_APP_LOG_DIR/cron-whenever.log

  # cron requires a home directory.  Make sure it exists and is owned by $EB_APP_USER.
  mkdir -p /home/$EB_APP_USER
  chown $EB_APP_USER:$EB_APP_USER /home/$EB_APP_USER

  # Set up correct environment and ruby version so that bundle can load all gems
  . $EB_SUPPORT_DIR/envvars
  . $EB_SCRIPT_DIR/use-app-ruby.sh

  # Run the whenever --update command to update the cron job for $EB_APP_USER.
  cd $EB_APP_DEPLOY_DIR
  whenever --update -u $EB_APP_USER

  # After setup, you can run "crontab -l -u webapp" to check the configuration.
timboon
  • 107
  • 1
  • 12

3 Answers3

1

First off - is that how your .config file is formatted? The file is in YAML format, so whitespace/indenting is important. Also, can you confirm what the file is called and where it is located? Should look like this:

.ebextensions/01-whenever.config

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/99_update_cron.sh"
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      . /opt/elasticbeanstalk/containerfiles/envvars
      su -c "cd $EB_CONFIG_APP_CURRENT; bundle exec whenever --update-cron" - $EB_CONFIG_APP_USER

If that doesn't fix it, check to make sure that the file /opt/elasticbeanstalk/hooks/appdeploy/post/99_update_cron.sh is being created correctly by connecting via eb ssh.

Then, check the log file at /var/log/eb-activity.log and look for the section where your 99_update_cron.sh hook is being executed. There may be some informative error messages.

Brian
  • 5,300
  • 2
  • 26
  • 32
  • Seems to be interacting with Cron as I am now getting log files - may I ask a follow up question? I am now getting `uninitialized constant Rails::Command::RunnerCommand::Trendi` error in the log - which I don't have in development mode - any ideas where to start looking for this, is it something to do with my lib tasks not getting bundled to AWS? I have added this to my config file `config.autoload_paths << Rails.root.join('lib')` – timboon Jan 09 '18 at 16:24
  • Hmm, that error message doesn't ring any bells. Could you post the entire relevant section from the log file? Everything from `[2018-01-09T19:50:20.461Z] INFO [4236] - [Application update app-x_xx-xxx-xxxxx-xxxxxx_xxxxxx@xxx/AppDeployStage1/AppDeployPostHook/99_update_cron.sh] : Starting activity...` to `[2018-01-09T19:50:20.468Z] INFO [4236] - [Application update app-x_xx-xxx-xxxxx-xxxxxx_xxxxxx@xxx/AppDeployStage1/AppDeployPostHook/99_update_cron.sh] : Completed activity.`? You could also try running locally in production mode via `RAILS_ENV=production rails s`. – Brian Jan 09 '18 at 21:28
  • added to original question - I also had to change the config file as your above answer was not working :( Will update question with new config file – timboon Jan 10 '18 at 00:18
  • Note Trendi is the name of the Task I am trying to run with cron - located in my lib directory – timboon Jan 10 '18 at 00:18
  • When you say `my lib directory`, is that at the top level of your project? I had a strange problem once where a file under `lib` wasn't being loaded in production. Moving the file to `app/lib` fixed the problem without any `autoload_paths` additions. – Brian Jan 10 '18 at 20:30
  • Oh really? That's weird I'll check when I get home – timboon Jan 10 '18 at 21:04
1

2022 AWS EB CHANGED - LINUX 2

Note if you are running the newer LINUX 2 platform on elastic beanstalk, the custom platform hooks most people refer to here are deprecated and instead you need to do the following:

create a simple shell script in the new .platform/hooks/postdeploy directory (create it if it doesn't exist).

.platform/hooks/postdeploy/01_whenever.sh

#!/usr/bin/env bash
cd /var/app/current
bundle exec whenever --update-crontab

However there is a catch, if you need any environment variables that are not in rails credentials or .env files, the environment variables are not available to the system so when your cron task runs, if it needs to for example to run rails, rails will break since it doesn't have access to the env variables.

To solve this, you need to either, move those variables into rails credentials or .env or make the eb env vars available to the system (see below).

under .ebextensions create a file called 01_export_vars.config

commands:
  setvars:
    command: /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export \(.key)=\"\(.value)\""' > /etc/profile.d/sh.local
packages:
  yum:
    jq: []

Now, when cron runs rails it will have access to eb env vars and run correctly.

Do note, that if you add a new eb env var you need to redeploy so that this script gets run again and exports that eb env var.

This is the best solution I have found, but if someone knows a better way, please tell.

Brad
  • 8,044
  • 10
  • 39
  • 50
0

If you have multiple EC2 instances running and want to run Whenever only in one instance, you probably want the following config:

files:
  "/tmp/99_update_cron.template":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      # Using similar syntax as the appdeploy pre hooks that is managed by AWS
      set -xe

      EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
      EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
      EB_DEPLOY_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)

      . $EB_SUPPORT_DIR/envvars
      . $EB_SCRIPT_DIR/use-app-ruby.sh

      cd $EB_DEPLOY_DIR
      su -c "bundle exec whenever --update-cron"
      su -c "crontab -l"

container_commands:
  enable_cron:
    command: "mv /tmp/99_update_cron.template /opt/elasticbeanstalk/hooks/appdeploy/post/99_update_cron.sh"
    leader_only: true
shaam
  • 106
  • 14