TL;DR:
See working .ebextentions
configuration at the end of answer.
Environment
如何使用crontab运行Laravel代码?
The answers to this question is of course the most obvious and if you're even the slightest in to Laravel you surely know the answer: Scheduling!
I won't bore you with explaining the brilliant thing that is Laravel Scheduling since you can read about it in the documentation yourself.
But the key thing we need to take with us is that Laravel Scheduling uses crontab to execute, as described in the documentation:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Which brings us to the next, and a bit more tricky, question...
How do I setup crontab in my Elastic Beanstalk environment?
乍一看,这个问题的答案似乎相当直截了当.我在AWS知识中心找到了这个:How do I create a cron job on EC2 instances in an Elastic Beanstalk environment?
Here they describe how to setup a cron job on your Elastic Beanstalk EC2 machine using .ebextentions. In short what it does is creating a new file in the directory /etc/cron.d/
in which we put our desired cron job.
Files in this directory is then processed by crontab as the root
user. There are some of the traps I walked in to, as I've commented below:
files:
# The name of the file should not contain any dot (.) or dash (-), this can
# cause the script not to run. Underscore (_) is OK.
"/etc/cron.d/mycron":
# This permissions is important so that root user can run the script.
mode: "000644"
# As the file is run by the root user it needs to be the owner of the file.
owner: root
# For consistency it's a good idea to have root as the group aswell.
group: root
# NOTE: We need to explicitly tell the cron job to be run as the root user!
content: |
* * * * * root /usr/local/bin/myscript.sh
# There need to be a new line after the actual cron job in the file.
一旦我们清除了所有这些trap ,就可以放入上面的Laravel调度cron作业(job)了.它应该看起来像这样:
files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
This won't really work in most cases though.这是因为Laravel调度程序无法访问您的ENV变量,显然不能访问您的数据库设置.
I found the answer to this here: How to Get Laravel Task Scheduling Working on AWS Elastic Beanstalk Cron
So a big shout out to George Bönnisch; I salute you sir for sharing this!
So with this last piece of the puzzle I was finally able to get the setup to work properly:
Working Solution
File structure:
[Project root]
|-- .ebextensions
| |-- cronjob.config
cronjob.config:
files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/artisan schedule:run 1>> /dev/null 2>&1
commands:
remove_old_cron:
command: "rm -f /etc/cron.d/*.bak"
Tip when using Laravel Scheduling on AWS Elastic Beanstalk!
Since one of the key features of Elastic Beanstalk is that it can autoscale and add more servers when needed, you might want to have a look on the new feature in Laravel Scheduling: Running Tasks On One Server.
在许多情况下,您不希望在多台服务器上执行cron作业(job).例如,如果您有一个用于发送邮箱的计划命令,您不希望多次发送这些命令.
NOTE:这要求您使用memcached或redis作为缓存引擎,如文档中所述.如果没有,请看一下AWS服务Elasticache.
NOTE 2:使用onOneServer()
时,必须使用name()
方法为计划任务命名(在调用onOneServer()
之前).如下所示:
$schedule->command('my:task')
->name('my:task')
->daily()
->onOneServer();