脚本

As a fairly new user of Laravel and Elastic Beanstalk I soon found my self in the need to schedule operations, like most of us do.

在过go ,我总是使用简单的crontab调度来实现这一点.所以现在我站在一系列问题面前:

  • How do I run Laravel code using crontab?
  • How do I setup crontab in my Elastic Beanstalk environment?

Finding the individual answers to these questions weren't that hard. Combining them and actually getting it all to work however turned out to be a bit tricky, which is why I've decided to share the solution here for others struggling with getting this to work properly.


环境

  • Laravel 5.6
  • PHP 7.1

推荐答案

TL;DR:

See working .ebextentions configuration at the end of answer.


Environment

  • Laravel 5.6
  • PHP 7.1

如何使用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();

Laravel相关问答推荐

我的共享主机上的每个帖子请求都出现 503 服务不可用

如何从@foreach 循环中捕获所有数据并将其传递给 值? - Laravel

使用 App::environment() 与 app()->environment() 与 config('app.env') 之间的区别

如何在 Laravel 5 中添加我自己的自定义类?

Laravel Valet 安装后 Ping test.dev 返回未知主机

使用 Amazon S3 的 Storage::get() 返回 false

如何在 Laravel Passport 中获取刷新令牌?

Laravel:如何通过 id 从集合中删除项目

如何在 laravel 中使用 str_replace

路由中间的可选参数

条带 api 判断现有卡

将 Laravel Socialite 与 API 一起使用?

SQLSTATE [01000]:警告:1265 列的数据被截断(truncated)

Array_unique 上一个 laravel Eloquent的集合

Laravel 分页方法不适用于 map 集合?

Laravel Eloquent 在子查询中有两个WHERE NOT IN

Laravel 4 上传图片表单

laravel 搜索多个以空格分隔的单词

Laravel 中的单会话登录

如何判断是否在laravel中使用了分页