Whenever Gem AWS elastic beanstalk - ruby-on-rails

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.

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.

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

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.

Related

How do I run delayed_jobs in Kubernetes?

I can log into console from one of the pods (on kubernetes) and run this command:
RAILS_ENV=production bin/delayed_job start
The jobs are run correctly doing that. However when the pods are deleted or restarted, the jobs stop running.
I also tried adding the command above in an initializer file (eg config/initializers/delayed_jobs_runner.rb), but I get a recursive loop when starting the app.
Another thing I tried to do is create a new file called my-jobs.yaml with this
apiVersion: batch/v1
kind: Job
metadata:
name: job
spec:
template:
spec:
containers:
- name: job
image: gcr.io/test-app-123/somename:latest
command: ["/bin/bash", "-l", "-c"]
args: ["RAILS_ENV=production bundle exec rake jobs:work"]
restartPolicy: Never
backoffLimit: 4
I then do kubectl apply -f my-jobs.yaml, but the jobs aren't running.
Any idea how to run delayed_jobs correctly in kubernetes?
EDIT: Here's my Dockerfile:
FROM gcr.io/google_appengine/ruby
# Install 2.5.1 if not already preinstalled by the base image
RUN cd /rbenv/plugins/ruby-build && \
git pull && \
rbenv install -s 2.5.1 && \
rbenv global 2.5.1 && \
gem install -q --no-rdoc --no-ri bundler
# --version 1.11.2
ENV RBENV_VERSION 2.5.1
# Copy the application files.
COPY . /app/
# Install required gems.
RUN bundle install --deployment && rbenv rehash
# Set environment variables.
ENV RACK_ENV=production \
RAILS_ENV=production \
RAILS_SERVE_STATIC_FILES=true
# Run asset pipeline.
RUN bundle exec rake assets:precompile
CMD ["setup.sh"]
# Reset entrypoint to override base image.
ENTRYPOINT ["/bin/bash"]
################### setup.sh ############################
cd /app && RAILS_ENV=production bundle exec script/delayed_job -n 2 start
bundle exec foreman start --formation "$FORMATION"
#########################################################
Running multiple processes in one docker container is problematic as you cannot easily observe lifetime of particular process - every container need one process which is "main" and when it exit, container also exit.
As looking on Github (https://github.com/collectiveidea/delayed_job#user-content-running-jobs) I would strongly suggest to change a little your starting command to run it in foreground because now when you are starting Kubernetes job with daemons
- job is ending immediately as docker container lifetime is directly related to "main" foreground process lifetime so when you run only background process your main process exit immediately and your container too.
Change your command to:
RAILS_ENV=production script/delayed_job run
What start worker in foreground so your Kubernetes Job won't exit. Please note also that Kubernetes Jobs are not intended to such infinitive tasks (job should has start and end) so I would suggest to use ReplicaSet for that
Now I am doing this:
this_pid=$$
(while [[ $(ps -ef | grep delayed_job | grep -v -e grep -e tail | head -c1 | wc -c) -ne 0 ]]; do sleep 10; done; kill -- -$this_pid) &
after starting multiple workers. And after this I tail -f the logs so that those go to the standard output of the container. I am quite crazy, so I am also running logrotate to keep the logs in check. The rails environment is pretty big anyway, so the container needs to be pretty big, and we need to be able to run many jobs and I don't want many pods running to do so. This seems to be efficient and will stop and restart if the workers die for some reason.

cron jobs not working aws whenever gem rails

I know this is a very common question but I feel like I need a specific answer to help find out where I am going wrong...
Loaded whenever gem to manage cron jobs - it works fine in development but when I loaded the app into AWS I can't seem to it work...
When I SSH into the instance I can run crontab -l and it lists the whenever tasks but it just doesn't seem to actually execute them. I also cant find any log files to read into why it's not firing.
This is what I pulled from the eb activity log..
+++ GEM_ROOT=/opt/rubies/ruby-2.3.6/lib/ruby/gems/2.3.0
++ (( 0 != 0 ))
+ cd /var/app/current
+ su -c 'bundle exec whenever --update-cron'
[write] crontab file updated
+ su -c 'crontab -l'
# Begin Whenever generated tasks for:
/var/app/current/config/schedule.rb at: 2018-01-10 06:08:24 +0000
0 * * * * /bin/bash -l -c 'cd /var/app/current && bundle exec
bin/rails runner -e production '\''Trendi.home'\'' >>
app/views/pages/cron.html.erb 2>&1'
# End Whenever generated tasks for:
/var/app/current/config/schedule.rb at: 2018-01-10 06:08:24 +0000
[2018-01-10T06:08:24.705Z] INFO [15603] - [Application update app-
a3a0-180109_230627#16/AppDeployStage1/AppDeployPostHook] : Completed
activity. Result:
Successfully execute hooks in directory
/opt/elasticbeanstalk/hooks/appdeploy/post.
This is my config file from ebextensions folder
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/01_cron.sh":
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"
My Schedule.rb
ENV['RAILS_ENV'] = "production"
set :output, "app/views/pages/cron.html.erb"
every 1.hour, at: ":00"do # 1.minute 1.day 1.week 1.month 1.year
is also supported
runner "Trendi.home", :environment => 'production'
end
And my task that is stored at /lib/
module Trendi
def self.home
#exectuted task code here
end
You could try a simpler command in your crontab and change it to fire every minute. E.g.
/bin/echo "test" >> /home/username/testcron.log
That way you can quickly rule out if it's the cronjob that's the culprit. Keep in mind to use full paths to each command. So in your case you might want to change the "bundle" command to use the full path. You can find the path with the "which" command.
Also, are you sure you are correctly escaping here?
-e production '\''Trendi.home'\''
Wouldn't this be more adequate?
-e production "Trendi.home"

Elastic Beanstalk: what's the best way to create folders & set permissions after deploy?

I'm running a Rails 4.2 app on Elastic Beanstalk, and need to set log permissions and create the /tmp/uploads folder (plus permissions) after deploy.
I was running two ebextensions scripts to do this, but on some occasions they would fail because the folder /var/app/current/ didn't yet exist.
I'm presuming this is because the permissions and/or folders should be created on /app/ondeck/ first so that EB can copy the contents over to /var/app/current/, but I'm interested to see if there's a recommended and more foolproof approach to doing this?
For reference, my two ebextension scripts were:
commands:
01_set_log_permissions:
command: "chmod 755 /var/app/current/log/*"
and
commands:
01_create_uploads_folder:
command: "mkdir -p /var/app/current/tmp/uploads/"
02_set_folder_permission:
command: "chmod 755 /var/app/current/tmp/uploads/"
Thanks,
Dan
you should probably use files tag and not command:
commands:
create_post_dir:
command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
ignoreErrors: true
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_make_changes.sh":
mode: "000777"
content: |
#!/bin/bash
mkdir -p /var/app/current/tmp/uploads/
chmod 755 /var/app/current/tmp/uploads/
it will be triggered after app deploy finished
I've used the below stpes:
Create a folder .ebextensions
Creta a file .config
Move .config to .ebextensions
Edit the file .config, it must have the below sintaxe
commands:
command1:
command: mkdir /opt/jenkins
command2:
command: chmod 644 /opt/jenkins
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#linux-commands
* Pay Attention *
You cannot run again command1 "mkdir /opt/jenkins", you will have a error, so you must do a test before.
What about using Container Commands?
http://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/customize-containers-ec2.html#linux-container-commands
You can use the container_commands key to execute commands for your container. The commands in container_commands are processed in alphabetical order by name. They run after the application and web server have been set up and the application version file has been extracted, but before the application version is deployed. They also have access to environment variables such as your AWS security credentials.
Container commands are run from the staging directory, where your source code is extracted prior to being deployed to the application server. Any changes you make to your source code in the staging directory with a container command will be included when the source is deployed to its final location.
container_commands:
01_set_log_permissions:
command: "chmod 755 log/*"
and
container_commands:
01_create_uploads_folder:
command: "mkdir -p tmp/uploads/"
02_set_folder_permission:
command: "chmod 755 tmp/uploads/"

AWS Elastic Beanstalk and Whenever Gem

I have a Rails 4.2.1 app, using Ruby 2.2. I'm trying to use the Whenever Gem to update cron tasks on my Elastic Beanstalk from my code base. I've followed a few resources from AWS where you can add files to the .ebextensions folder and use EB's post deployment hook via shell files. Here are a couple resources:
https://forums.aws.amazon.com/thread.jspa?threadID=137136
http://www.dannemanne.com/posts/post-deployment_script_on_elastic_beanstalk_restart_delayed_job
http://blog.endpoint.com/2015/01/elastic-beanstalk-whenever.html
Following the blog articles, I added the file below, uncommented the gitignore line about files in the .ebextensions folder, and deployed my app. Unfortunatley, I have been able to see any changes. I've checked the log files (log/eb-tools.log, log/cron, etc.), and grepped all the log files for the shell file I create, whenever, and more. No luck though.
commands:
create-post-dir:
command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
ignoreErrors: true
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_update_cron.sh"
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
# Using similar syntax as the appdeploy pre hooks that is managed by AWS
# Loading 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_CURRENT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
EB_APP_PIDS_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
# Setting up correct environment and ruby version so that bundle can load all gems
. $EB_SUPPORT_DIR/envvars
. $EB_SCRIPT_DIR/use-app-ruby.sh
# Now we can do the actual restart of the worker. Make sure to have double quotes when using env vars in the command.
su -c "cd $EB_APP_CURRENT_DIR; bundle exec whenever --update-cron --set='environment=$RACK_ENV'" - $EB_APP_USER
How can I make sure this shell file is getting called? Can I test it without a new deployment each time? Also, I'm open to other options if the Whenever gem is not the best option. I mainly want to be able to have my cron tasks managed in code and under version control.
Thanks in advance!
UPDATE:
I had a type on the .ebextensions folder, which was causing it to not be added. After that was fixed, I was able to read error messages, and create a cron script that updated the crontab using the Whenever gem.
I was able to figure this out after fixing a typo in my .ebextensions folder name. Afterwards, the scripts got compiled, and log messages started to appear. After reading the log messages, I came up with the following config script (.ebextensions/01_cron.config):
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/01_cron.sh":
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"

How to automatically restart delayed_job when deploying a rails project on Amazon Elastic Beanstalk?

I'm hosting a rails project on Amazon Elastic Beanstalk and I try to configure a container command to automatically restart my delayed_job worker on the server after each deployment.
I tried with this one :
container_commands:
restartdelayedjob:
command: "RAILS_ENV=production script/delayed_job --pid-dir=/home/ec2-user/pids start"
cwd: /var/app/current
But, it seems that the pushed version is deployed after the restarting of the worker so the jobs failed to be processed by the worker.
When I connect on my instance by ssh, kill the worker process and restart a new one from the deployed version folder, everything works fine.
Do you have any ideas of how I can handle this?
Thanks
As per the Amazon documentation for container_commands:
They run after the application and web server have been set up and the application version file has been extracted, but before the application version is deployed.
(emphasis mine)
This means at that point /var/app/current which you are setting as the cwd for your command is still pointing to the previous version. However by default, from the docs again, cwd:
is the directory of the unzipped application.
This means that if you want to run delayed_job from the directory of the app that just got extracted (but not yet deployed), don't override cwd and it should start the delayed_job for the app that's about to be deployed.
Ref: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#customize-containers-format-container_commands
Update:
I've now set this up myself and found there's limitations to doing it via the standard container_commands - basically delayed_job will be started while it is still in the /var/app/ondeck directory. Usually this is OK, but I had some issues with some jobs because that path had stuck around it would cause errors as the app was now in /var/app/current.
I found an undocumented (so warning!) approach that you can add scripts to be run AFTER your app server is restarted (and your new deploy is in /var/app/current).
Basically Elastic Beanstalk will execute any scripts in /opt/elasticbeanstalk/hooks/appdeploy/post after the web server is restarted. This means if you drop shell scripts in this directory they will be run.
I created a shell script like this:
#!/usr/bin/env bash
. /opt/elasticbeanstalk/support/envvars
cd $EB_CONFIG_APP_CURRENT
su -c "RAILS_ENV=production script/delayed_job --pid-dir=$EB_CONFIG_APP_SUPPORT/pids restart" $EB_CONFIG_APP_USER
I uploaded this script to an S3 bucket, and made sure it was "public". You can then use an options script in your .ebextensions directory (eg. 99delayed_job.config) to deploy this script as part of your app deploy, taking note that the post directory might not exist:
commands:
create_post_dir:
command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
ignoreErrors: true
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh":
mode: "000755"
owner: root
group: root
source: http://YOUR_BUCKET.s3.amazonaws.com/99_restart_delayed_job.sh
When you deploy you should see something like this in your /var/log/eb-tools.log:
2013-05-16 01:20:53,759 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Executing directory: /opt/elasticbeanstalk/hooks/appdeploy/post/
2013-05-16 01:20:53,760 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Executing script: /opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh
2013-05-16 01:21:02,619 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Output from script: delayed_job: trying to stop process with pid 6139...
delayed_job: process with pid 6139 successfully stopped.
2013-05-16 01:21:02,620 [INFO] (6467 MainThread) [directoryHooksExecutor.py-29] [root directoryHooksExecutor info] Script succeeded.
As I said, putting stuff in this "post" directory is undocumented - but hopefully at some point Amazon add actual support to the .options scripts to run commands post-deploy, in that case you could move this to the officially supported approach.
On 64bit Amazon Linux 2014.09 v1.1.0 running Ruby 2.1 (Passenger Standalone), got it working thanks to this post.
Note that this script is run as root, but your workers should be run as the webapp user.
# Adds a post-deploy hook such that after a new version is deployed
# successfully, restarts the delayed_job workers.
#
# http://stackoverflow.com/questions/14401204/how-to-automatically-restart-delayed-job-when-deploying-a-rails-project-on-amazo
# http://www.dannemanne.com/posts/post-deployment_script_on_elastic_beanstalk_restart_delayed_job
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/50_restart_delayed_job.sh":
mode: "000755"
owner: root
group: root
encoding: plain
content: |
#!/usr/bin/env bash
EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
EB_APP_CURRENT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
EB_APP_PIDS_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
. $EB_SUPPORT_DIR/envvars
. $EB_SCRIPT_DIR/use-app-ruby.sh
cd $EB_APP_CURRENT_DIR
# Switch to the webapp user. Worker shouldn't be run as root.
su -s /bin/bash -c "bundle exec bin/delayed_job --pid-dir=$EB_APP_PIDS_DIR restart" $EB_APP_USER
In case anybody is looking to get delayed_job working in latest ElasticBeanstalk (64bit Amazon Linux 2014.09 v1.0.9 running Ruby 2.1 (Puma)): I got it to work using the below code (Thanks to damontorgerson). This file goes in ruby.config in .ebextensions folder.
# Install git in order to be able to bundle gems from git
packages:
yum:
git: []
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/50_restart_delayed_job":
mode: "000777"
owner: root
group: root
content: |
EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
EB_CONFIG_APP_CURRENT=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
EB_CONFIG_APP_LOGS=$(/opt/elasticbeanstalk/bin/get-config container -k app_log_dir)
EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)
EB_CONFIG_APP_PIDS=$(/opt/elasticbeanstalk/bin/get-config container -k app_pid_dir)
. $EB_SUPPORT_DIR/envvars
. $EB_SCRIPT_DIR/use-app-ruby.sh
cd $EB_CONFIG_APP_CURRENT
. $EB_SUPPORT_DIR/envvars.d/sysenv
bin/delayed_job --pid-dir=/var/tmp restart
I got mine working like so with the "daemons" gem:
commands:
create_post_dir:
command: "mkdir /opt/elasticbeanstalk/hooks/appdeploy/post"
ignoreErrors: true
webapp_pids:
command: "mkdir /home/webapp/pids"
ignoreErrors: true
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/99_restart_delayed_job.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
. /opt/elasticbeanstalk/support/envvars
chown webapp:webapp /home/webapp/pids
su -l -c "$EB_CONFIG_APP_CURRENT/bin/delayed_job --pid-dir=/home/webapp/pids restart" $EB_CONFIG_APP_USER
echo "worker starting" >> /var/log/directory-hooks-executor.log

Resources