如何在AWS Elastic Beanstalk上设置和使用Laravel调度? 脚本

如何在AWS Elastic Beanstalk上设置和使用Laravel调度? 脚本,laravel,amazon-web-services,cron,amazon-elastic-beanstalk,laravel-5.6,Laravel,Amazon Web Services,Cron,Amazon Elastic Beanstalk,Laravel 5.6,作为Laravel和Elastic Beanstalk的新用户,我很快发现自己需要安排操作,就像我们大多数人一样 在过去,我总是使用简单的crontab调度来实现这一点。现在我站在一系列问题面前: 如何使用crontab运行Laravel代码? 如何在Elastic Beanstalk环境中设置crontab? 找到这些问题的个人答案并不难。然而,将它们结合起来并使其真正发挥作用却有点棘手,这就是为什么我决定在这里为那些努力使其正常发挥作用的人分享解决方案的原因 环境 拉威尔5.6 PH

作为Laravel和Elastic Beanstalk的新用户,我很快发现自己需要安排操作,就像我们大多数人一样

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

  • 如何使用crontab运行Laravel代码?
  • 如何在Elastic Beanstalk环境中设置crontab?
找到这些问题的个人答案并不难。然而,将它们结合起来并使其真正发挥作用却有点棘手,这就是为什么我决定在这里为那些努力使其正常发挥作用的人分享解决方案的原因


环境
  • 拉威尔5.6
  • PHP7.1
TL;博士: 请参阅答案末尾的工作
.ebextensions
配置


环境
  • 拉威尔5.6
  • PHP7.1

如何使用crontab运行Laravel代码? 这个问题的答案当然是最明显的,如果你对拉雷维尔有一点点了解,你肯定知道答案:

我不会让你感到厌烦,因为你可以自己在文档中读到关于Laravel日程安排的精彩内容

但我们需要带上的关键是,Laravel调度使用crontab执行,如文档中所述:

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
这就引出了下一个更棘手的问题


如何在Elastic Beanstalk环境中设置crontab? 乍一看,这个问题的答案似乎很直截了当。我在AWS Knownledge中心找到了这个:

这里他们描述了如何使用.ebextentions在Elastic Beanstalk EC2机器上设置cron作业。简而言之,它所做的是在目录
/etc/cron.d/
中创建一个新文件,我们将所需的cron作业放在其中

然后,crontab以
root
用户的身份处理此目录中的文件。正如我在下面评论的那样,我遇到了一些陷阱:

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.
一旦我们清除了所有这些陷阱,是时候从上面开始我们的Laravel调度cron作业了。应该是这样的:

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
不过,这在大多数情况下都不起作用。这是因为Laravel调度程序无法访问您的ENV变量,显然不能访问您的数据库设置

我在这里找到了答案:

对乔治·本尼希大吼一声;先生,我向您致敬,感谢您与我分享

因此,通过这最后一块拼图,我终于能够让设置正常工作:


工作溶液 文件结构:

[Project root]
    |-- .ebextensions
    |        |-- 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"
cronjob.config:

[Project root]
    |-- .ebextensions
    |        |-- 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"

在AWS Elastic Beanstalk上使用Laravel调度时的提示! 由于Elastic Beanstalk的关键功能之一是,它可以在需要时自动缩放并添加更多服务器,因此您可能希望了解Laravel Scheduling中的新功能:

在许多情况下,您不希望在多个服务器上执行cron作业。例如,如果您有一个发送电子邮件的预定命令,您不希望这些邮件被发送多次

注意:这要求您使用memcached或redis作为缓存引擎,如文档中所述。如果没有,请查看AWS服务

注意2:当使用
onOneServer()
时,必须使用
name()
方法(在调用
onOneServer()
之前)为计划任务指定一个名称。像这样:

$schedule->command('my:task')
    ->name('my:task')
    ->daily()
    ->onOneServer();

更简单的方法是使用新的定期任务功能。对cron作业使用
.ebextensions
可能会导致多台机器运行同一作业或具有自动缩放功能的其他竞争条件

cron.yaml
中定义的作业仅由辅助环境加载,并保证一次仅由一台机器(领导者)运行。它有一个很好的同步机制,以确保没有重复。从文档中:

Elastic Beanstalk使用领导人选举来确定工作环境中的哪个实例对定期任务进行排队。每个实例都试图通过写入AmazonDynamodB表来成为领导者。第一个成功的实例是leader,并且必须继续写入表以保持leader状态。如果领导者离职,另一个例子很快就会取代他的位置

为单个或多个工作进程创建Cron 将
cron.yaml
放在项目的根目录中:

version: 1
cron:
  - name: "schedule"
    url: "/worker/schedule"
    schedule: "* * * * *"
需要考虑的一点是,在Beanstalk中,周期性任务被设计为向应用程序中的URL发出HTTP POST请求,从而触发要运行的作业。这类似于它使用SQS管理队列的方式

为了拉威尔 特别是对于Laravel,您可以创建路由和控制器来处理每个计划作业。但更好的方法是使用Laravel的调度程序,并拥有一条每分钟调用一次的路由

此程序包将自动为您创建这些路由

权限疑难解答 如果您在从CodePipeline触发部署时遇到DynamoDB create Leader表权限问题,那是因为CodePiLine服务角色需要
DynamoDB:CreateTable
。有关说明,请检查这些


在AWS ECS中,我们可以在不向容器中添加cron的情况下使用它

以下是启动无cronless计划的方法:

php artisan schedule:run-cronless

这是给docker用户的,有一些问题,所以认为它值得发布

cron需要添加到服务器上的
schedule\u run
文件中。但是,即使在
dockrun.aws.json
文件中添加了
container\u name
,它也会将其更改为该文件,再加上一些额外的信息,因此无法使用正常的服务名称来运行cron

所以使用
$(docker ps