Create a cron job in AWS’s Elastic Beanstalk using Django
This article will tell you how to write a cron job in AWS’s Elastic Beanstalk (EB) using Django. For reference, my EB environment is using Python 3.7 running on 64bit Amazon Linux 2/3.1.3. It is probably different if you’re using a different version.
Step 1 — Create the file you want to run
The example file I used is up on github here. It is a simple scraper that pulls NFL’s Next Gen Statistics and pushes them to the local database. Your file will be stored in the directory <application>/management/commands/<file_name.py>
That naming convention is needed, as it allows you to type python manage.py <file_name> to run that file. Just a reminder that you need the class Command(BaseCommand) in order for it to run properly.
from django.core.management.base import BaseCommand, CommandErrorclass Command(BaseCommand):
def handle(self, *args, **options):
pass # here is where you will start your function
Step 2 — Create your crons.config file
Once your file is created, you will then create a file in the project directory .ebextensions/crons.config
This will hold all of your crons job. There is a lot to take in, so you might have to just copy and paste it in your own file (lol). In the places where I put <> it’s where you put your own values.
The first part checks if there are multiple EC2 instances, and if there are only use 1 instance for cron jobs.
The final part removes all the cron jobs, so when you reupload this it will not put the same cron job multiple times.
files:
"/usr/local/bin/check_leader_only_instance.sh":
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
INSTANCE_ID=`curl http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null`
REGION=`curl -s http://169.254.169.254/latest/dynamic/instance-identity/document 2>/dev/null | jq -r .region` # Find the Auto Scaling Group name from the Elastic Beanstalk environment
ASG=`aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" \
--region $REGION --output json | jq -r '.[][] | select(.Key=="aws:autoscaling:groupName") | .Value'`
# Find the first instance in the Auto Scaling Group
FIRST=`aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG \
--region $REGION --output json | \
jq -r '.AutoScalingGroups[].Instances[] | select(.LifecycleState=="InService") | .InstanceId' | sort | head -1` # If the instance ids are the same exit 0
[ "$FIRST" = "$INSTANCE_ID" ] "/usr/local/bin/cron_<cron_name>.sh":
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
/usr/local/bin/check_leader_only_instance.sh || exit
source /var/app/venv/*/bin/activate
cd /var/app/current
python manage.py <whatever your python name is> "/etc/cron.d/daily_cron":
mode: "000644"
owner: root
group: root
content: |
* * * * * root /usr/local/bin/cron_<cron_name>.shcontainer_commands:
rm_old_cron:
command: "rm -fr /etc/cron.d/*.bak"
ignoreErrors: true
Step 3 — Push!
Run eb deploy, and once it’s all setup you’re good to go! That’s how you create a cron job and push it to AWS.