我想知道是否有办法设置每分钟执行一次cronjob /任务 . 目前,我的任何实例都应该能够运行此任务 .
这是我在配置文件中尝试做的事情没有成功:
container_commands: 01cronjobs: command: echo "*/1 * * * * root php /etc/httpd/myscript.php"
我不确定这是否是正确的方法
有任何想法吗?
如果您使用的是Rails,则可以使用whenever-elasticbeanstalk gem . 它允许您在所有实例上运行cron作业或只运行一个 . 它会检查每分钟以确保只有一个"leader"实例,并且如果没有,则会自动将一个服务器提升为"leader" . 这是必需的,因为Elastic Beanstalk在部署期间仅具有leader的概念,并且可以在扩展时随时关闭任何实例 .
UPDATE 我转而使用AWS OpsWorks,不再维护此gem . 如果您需要比Elastic Beanstalk基础知识更多的功能,我强烈建议您切换到OpsWorks .
在应用程序的根目录下创建一个名为.ebextensions的文件夹(如果该文件夹尚不存在) . 然后在.ebextensions文件夹中创建一个配置文件 . 我将使用example.config进行说明 . 然后将其添加到example.config
container_commands: 01_some_cron_job: command: "cat .ebextensions/some_cron_job.txt > /etc/cron.d/some_cron_job && chmod 644 /etc/cron.d/some_cron_job" leader_only: true
这是Elastic Beanstalk的YAML配置文件 . 确保将其复制到文本编辑器中时,文本编辑器使用空格而不是制表符 . 否则,当您将其推送到EB时,您将收到YAML错误 .
这样做的是创建一个名为01_some_cron_job的命令 . 命令按字母顺序运行,因此01确保它作为第一个命令运行 .
然后,该命令获取名为some_cron_job.txt的文件的内容,并将其添加到/etc/cron.d中名为some_cron_job的文件中 .
然后,该命令将更改/etc/cron.d/some_cron_job文件的权限 .
leader_only键确保命令仅在被视为领导者的ec2实例上运行 . 而不是在每个ec2实例上运行,而不是运行 .
然后在.ebextensions文件夹中创建一个名为some_cron_job.txt的文件 . 您将把cron作业放在此文件中 .
例如:
# The newline at the end of this file is extremely important. Cron won't run without it. * * * * * root /usr/bin/php some-php-script-here > /dev/null
所以这个cron作业将以root用户的身份每天每小时运行一次,并将输出丢弃到/ dev / null . / usr / bin / php是php的路径 . 然后用你的php文件的路径替换some-php-script-here . 这显然是假设您的cron作业需要运行PHP文件 .
另外,请确保some_cron_job.txt文件在文件末尾有一个换行符,就像评论所说的那样 . 否则cron将无法运行 .
Update: 当Elastic Beanstalk扩展您的实例时,此解决方案存在问题 . 例如,假设您有一个运行cron作业的实例 . 您的流量会增加,因此Elastic Beanstalk会将您扩展到两个实例 . leader_only将确保您只在两个实例之间运行一个cron作业 . 您的流量减少,Elastic Beanstalk将您缩减为一个实例 . 但是,Elastic Beanstalk不是终止第二个实例,而是终止作为领导者的第一个实例 . 您现在没有运行任何cron作业,因为它们仅在已终止的第一个实例上运行 . See the comments below.
Update 2: 从以下评论中明确说明:AWS现在可以防止自动实例终止 . 只需在领导者实例上启用它,然后在9:23启用它
根据目前的文档,其中一个是所谓的worker tier .
引用文档:
AWS Elastic Beanstalk支持在运行预定义配置的环境中的工作线程环境层的定期任务,其中包含容器名称中包含“v1.2.0”的解决方案堆栈 . 您必须创建一个新环境 .
有趣的是关于cron.yaml的部分:
要调用定期任务,应用程序源包必须在根级别包含cron.yaml文件 . 该文件必须包含有关要安排的定期任务的信息 . 使用标准crontab语法指定此信息 .
Update: 我们得到了这项工作 . 以下是我们的经验(Node.js平台)的一些重要问题:
使用cron.yaml文件时,请确保您拥有最新的awsebcli,因为旧版本无法正常运行 .
创造新环境也至关重要(至少在我们的情况下是这样),而不仅仅是克隆旧环境 .
如果要确保EC2工作器层实例支持CRON,请将ssh插入其中( eb ssh ),然后运行 cat /var/log/aws-sqsd/default.log . 它应报告为 aws-sqsd 2.0 (2015-02-18) . 如果您没有2.0版本,那么在创建环境时出现问题,您需要创建一个如上所述的新环境 .
eb ssh
cat /var/log/aws-sqsd/default.log
aws-sqsd 2.0 (2015-02-18)
关于jamieb的响应,并且如alrdinleal所提到的,您可以使用'leader_only'属性来确保只有一个EC2实例运行cron作业 .
报价取自http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html:
你可以使用leader_only . 选择一个实例作为Auto Scaling组的领导者 . 如果leader_only值设置为true,则该命令仅在标记为leader的实例上运行 .
我试图在我的eb上实现类似的东西,所以如果我解决它将更新我的帖子 .
UPDATE:
好吧,我现在使用以下eb配置工作cronjobs:
files: "/tmp/cronjob" : mode: "000777" owner: ec2-user group: ec2-user content: | # clear expired baskets */10 * * * * /usr/bin/wget -o /dev/null http://blah.elasticbeanstalk.com/basket/purge > $HOME/basket_purge.log 2>&1 # clean up files created by above cronjob 30 23 * * * rm $HOME/purge* encoding: plain container_commands: purge_basket: command: crontab /tmp/cronjob leader_only: true commands: delete_cronjob_file: command: rm /tmp/cronjob
本质上,我使用cronjobs创建一个临时文件,然后将crontab设置为从临时文件中读取,然后删除临时文件 . 希望这个帮助 .
如上所述, Build 任何crontab配置的根本缺陷是它只在部署时发生 . 随着群集自动放大,然后退回,最好也是第一个关闭的服务器 . 此外,没有故障转移,对我来说这是至关重要的 .
我做了一些研究,然后与我们的AWS账户专家交谈,以反映想法并确认我提出的解决方案 . 你可以用OpsWorks完成这个,虽然它有点像用房子来杀死苍蝇 . 也可以使用Data Pipeline with Task Runner,但这在它可以执行的脚本中的能力有限,我需要能够运行PHP脚本,并可以访问整个代码库 . 您还可以在ElasticBeanstalk集群之外专用EC2实例,但之后您不会再进行故障转移 .
所以这就是我想出来的,这显然是非常规的(正如AWS代表评论的那样)并且可能被认为是一种黑客攻击,但它可以运行并且可以通过故障转移实现 . 我选择了使用SDK的编码解决方案,我将在PHP中展示,尽管您可以使用您喜欢的任何语言执行相同的方法 .
// contains the values for variables used (key, secret, env) require_once('cron_config.inc'); // Load the AWS PHP SDK to connection to ElasticBeanstalk use Aws\ElasticBeanstalk\ElasticBeanstalkClient; $client = ElasticBeanstalkClient::factory(array( 'key' => AWS_KEY, 'secret' => AWS_SECRET, 'profile' => 'your_profile', 'region' => 'us-east-1' )); $result = $client->describeEnvironmentResources(array( 'EnvironmentName' => AWS_ENV )); if (php_uname('n') != $result['EnvironmentResources']['Instances'][0]['Id']) { die("Not the primary EC2 instance\n"); }
通过这个以及如何操作......你可以像往常一样在每个EC2实例上调用crontab中的脚本 . 每个脚本在开头都包含它(或者每个脚本包含一个文件,因为我使用它),它 Build 一个ElasticBeanstalk对象并检索所有实例的列表 . 它仅使用列表中的第一个服务器,并检查它是否与自身匹配,如果它继续,它将继续,否则它将死亡并关闭 . 我已经检查过并且返回的列表似乎是一致的,从技术上讲,它只需要一分钟左右一致,因为每个实例都执行预定的cron . 如果确实发生了变化,那就无所谓了,因为它只与那个小窗口有关 .
这并不优雅,但适合我们的特定需求 - 这不是通过额外服务增加成本或必须拥有专用的EC2实例,并且在发生任何故障时都会进行故障转移 . 我们的cron脚本运行维护脚本,这些脚本放入SQS,集群中的每个服务器都有助于执行 . 如果符合您的需求,至少可以为您提供备用选项 .
-Davey
我与AWS支持代理进行了交谈,这就是我们如何为我工作的方式 . 2015解决方案:
使用your_file_name.config在.ebextensions目录中创建一个文件 . 在配置文件输入中:
files: "/etc/cron.d/cron_example": mode: "000644" owner: root group: root content: | * * * * * root /usr/local/bin/cron_example.sh "/usr/local/bin/cron_example.sh": mode: "000755" owner: root group: root content: | #!/bin/bash /usr/local/bin/test_cron.sh || exit echo "Cron running at " `date` >> /tmp/cron_example.log # Now do tasks that should only run on 1 instance ... "/usr/local/bin/test_cron.sh": mode: "000755" owner: root group: root content: | #!/bin/bash METADATA=/opt/aws/bin/ec2-metadata INSTANCE_ID=`$METADATA -i | awk '{print $2}'` REGION=`$METADATA -z | awk '{print substr($2, 0, length($2)-1)}'` # Find our Auto Scaling Group name. ASG=`aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" \ --region $REGION --output text | awk '/aws:autoscaling:groupName/ {print $5}'` # Find the first instance in the Group FIRST=`aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG \ --region $REGION --output text | awk '/InService$/ {print $4}' | sort | head -1` # Test if they're the same. [ "$FIRST" = "$INSTANCE_ID" ] commands: rm_old_cron: command: "rm *.bak" cwd: "/etc/cron.d" ignoreErrors: true
该解决方案有两个缺点:
在后续部署中,Beanstalk将现有的cron脚本重命名为.bak,但cron仍会运行它 . 你的Cron现在在同一台机器上执行两次 .
如果您的环境扩展,您将获得多个实例,所有实例都在运行您的cron脚本 . 这意味着您的邮件重复,或您的数据库存档重复
解决方法:
确保创建cron的任何.ebextensions脚本还会在后续部署中删除.bak文件 .
有一个帮助脚本,它执行以下操作: - 从元数据获取当前的实例ID - 从EC2标记获取当前的Auto Scaling组名称 - 获取该组中的EC2实例列表,按字母顺序排序 . - 从该列表中获取第一个实例 . - 将步骤1中的实例ID与步骤4中的第一个实例ID进行比较 . 然后,您的cron脚本可以使用此帮助程序脚本来确定它们是否应该执行 .
警告:
用于Beanstalk实例的IAM角色需要ec2:DescribeTags和autoscaling:DescribeAutoScalingGroups权限
从中选择的实例是Auto Scaling显示为InService的实例 . 这并不一定意味着它们已完全启动并准备好运行您的cron .
如果使用默认的beanstalk角色,则不必设置IAM角色 .
你真的不会有多个应用程序实例,这可能会导致竞争条件和其他奇怪的问题 . 我实际上recently blogged about this(页面上的第4或第5个提示) . 简短版本:根据应用程序,使用SQS等作业队列或iron.io等第三方解决方案 .
使用 files 而不是 container_commands 的更易读的解决方案:
files
container_commands
files: "/etc/cron.d/my_cron": mode: "000644" owner: root group: root content: | # override default email address MAILTO="example@gmail.com" # run a Symfony command every five minutes (as ec2-user) */10 * * * * ec2-user /usr/bin/php /var/app/current/app/console do:something encoding: plain commands: # delete backup file created by Elastic Beanstalk clear_cron_backup: command: rm -f /etc/cron.d/watson.bak
请注意,格式与通常的crontab格式不同,它指定用户运行命令 .
有人想知道leader_only自动扩展新领导者出现时的问题 . 我似乎无法弄清楚如何回复他们的评论,但看到这个链接:http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
以下是该解决方案的完整说明:
http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
要控制Auto Scaling在扩展时是否可以终止特定实例,请使用实例保护 . 您可以在Auto Scaling组或单个Auto Scaling实例上启用实例保护设置 . Auto Scaling启动实例时,实例将继承Auto Scaling组的实例保护设置 . 您可以随时更改Auto Scaling组或Auto Scaling实例的实例保护设置 .
http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection
我有另一个解决方案,如果需要通过cron运行php文件,如果你设置了任何NAT实例,那么你可以将cronjob放在NAT实例上并通过wget运行php文件 .
你只需要2分钟来配置它:
创建一个 Worker 层
安装laravel-aws-worker
composer require dusterio/laravel-aws-worker
将cron.yaml添加到应用程序的根文件夹中(这可以是您的repo的一部分,或者您可以在部署到EB之前添加此文件 - 重要的是该文件在部署时存在):
version: 1 cron: - name: "schedule" url: "/worker/schedule" schedule: "* * * * *"
现在将执行 App\Console\Kernel 中的所有任务
App\Console\Kernel
详细说明和解释:https://github.com/dusterio/laravel-aws-worker
如何在Laravel中编写任务:https://laravel.com/docs/5.4/scheduling
所以我们一直在努力解决这个问题,在与AWS代表进行一些讨论后,我终于想出了我认为最好的解决方案 .
使用带有cron.yaml的工作层绝对是最容易解决的问题 . 但是,文档没有说清楚的是,这会将作业放在您可接受的SQS队列的末尾,因为它取决于队列的大小 . 一种选择是使用一个完全独立的环境来运行cron作业,但我认为这太过分了 .
其他一些选项,例如检查您是否是列表中的第一个实例,也不理想 . 如果当前的第一个实例正在关闭,该怎么办?
实例保护也可能带来问题 - 如果该实例被锁定/冻结该怎么办?
重要的是要了解AWS如何管理cron.yaml功能 . 有一个SQS守护进程使用Dynamo表来处理“领导者选举” . 它经常写入此表,如果当前的领导者在短时间内没有写入,则下一个实例将接管为领导者 . 这是守护进程决定将作业触发到SQS队列的实例 .
我们可以重新利用现有功能,而不是尝试重写我们自己的功能 . 你可以在这里看到完整的解决方案:https://gist.github.com/dorner/4517fe2b8c79ccb3971084ec28267f27
这是在Ruby中,但您可以轻松地将其适用于具有AWS SDK的任何其他语言 . 从本质上讲,它检查当前的领导者,然后检查状态以确保它处于良好状态 . 它将循环直到当前领导者处于良好状态,并且如果当前实例是领导者,则执行该作业 .
这是一个修复,你想在PHP中这样做 . 你只需要在.ebextensions文件夹中使用cronjob.config就可以让它像这样工作 .
files: "/etc/cron.d/my_cron": mode: "000644" owner: root group: root content: | empty stuff encoding: plain commands: 01_clear_cron_backup: command: "rm -f /etc/cron.d/*.bak" 02_remove_content: command: "sudo sed -i 's/empty stuff//g' /etc/cron.d/my_cron" container_commands: adding_cron: command: "echo '* * * * * ec2-user . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/app/current/index.php cron sendemail > /tmp/sendemail.log 2>&1' > /etc/cron.d/my_cron" leader_only: true
envvars获取文件的环境变量 . 您可以像上面那样在tmp / sendemail.log上调试输出 .
希望这有助于某人,因为它肯定帮助了我们!
我对2018年的1美分贡献
这是正确的方法(使用 django/python 和 django_crontab app):
django/python
django_crontab
在 .ebextensions 文件夹里面创建一个像这样的文件 98_cron.config :
.ebextensions
98_cron.config
files: "/tmp/98_create_cron.sh": mode: "000755" owner: root group: root content: | #!/bin/sh cd / sudo /opt/python/run/venv/bin/python /opt/python/current/app/manage.py crontab remove > /home/ec2-user/remove11.txt sudo /opt/python/run/venv/bin/python /opt/python/current/app/manage.py crontab add > /home/ec2-user/add11.txt container_commands: 98crontab: command: "mv /tmp/98_create_cron.sh /opt/elasticbeanstalk/hooks/appdeploy/post && chmod 774 /opt/elasticbeanstalk/hooks/appdeploy/post/98_create_cron.sh" leader_only: true
它必须是 container_commands 而不是 commands
commands
16 回答
如果您使用的是Rails,则可以使用whenever-elasticbeanstalk gem . 它允许您在所有实例上运行cron作业或只运行一个 . 它会检查每分钟以确保只有一个"leader"实例,并且如果没有,则会自动将一个服务器提升为"leader" . 这是必需的,因为Elastic Beanstalk在部署期间仅具有leader的概念,并且可以在扩展时随时关闭任何实例 .
UPDATE 我转而使用AWS OpsWorks,不再维护此gem . 如果您需要比Elastic Beanstalk基础知识更多的功能,我强烈建议您切换到OpsWorks .
这就是我向Elastic Beanstalk添加一个cron作业的方法:
在应用程序的根目录下创建一个名为.ebextensions的文件夹(如果该文件夹尚不存在) . 然后在.ebextensions文件夹中创建一个配置文件 . 我将使用example.config进行说明 . 然后将其添加到example.config
这是Elastic Beanstalk的YAML配置文件 . 确保将其复制到文本编辑器中时,文本编辑器使用空格而不是制表符 . 否则,当您将其推送到EB时,您将收到YAML错误 .
这样做的是创建一个名为01_some_cron_job的命令 . 命令按字母顺序运行,因此01确保它作为第一个命令运行 .
然后,该命令获取名为some_cron_job.txt的文件的内容,并将其添加到/etc/cron.d中名为some_cron_job的文件中 .
然后,该命令将更改/etc/cron.d/some_cron_job文件的权限 .
leader_only键确保命令仅在被视为领导者的ec2实例上运行 . 而不是在每个ec2实例上运行,而不是运行 .
然后在.ebextensions文件夹中创建一个名为some_cron_job.txt的文件 . 您将把cron作业放在此文件中 .
例如:
所以这个cron作业将以root用户的身份每天每小时运行一次,并将输出丢弃到/ dev / null . / usr / bin / php是php的路径 . 然后用你的php文件的路径替换some-php-script-here . 这显然是假设您的cron作业需要运行PHP文件 .
另外,请确保some_cron_job.txt文件在文件末尾有一个换行符,就像评论所说的那样 . 否则cron将无法运行 .
Update: 当Elastic Beanstalk扩展您的实例时,此解决方案存在问题 . 例如,假设您有一个运行cron作业的实例 . 您的流量会增加,因此Elastic Beanstalk会将您扩展到两个实例 . leader_only将确保您只在两个实例之间运行一个cron作业 . 您的流量减少,Elastic Beanstalk将您缩减为一个实例 . 但是,Elastic Beanstalk不是终止第二个实例,而是终止作为领导者的第一个实例 . 您现在没有运行任何cron作业,因为它们仅在已终止的第一个实例上运行 . See the comments below.
Update 2: 从以下评论中明确说明:AWS现在可以防止自动实例终止 . 只需在领导者实例上启用它,然后在9:23启用它
这是现在正式开展的方式(2015年) . 请先尝试一下,这是目前最简单的方法,也是最可靠的方法 .
根据目前的文档,其中一个是所谓的worker tier .
引用文档:
有趣的是关于cron.yaml的部分:
Update: 我们得到了这项工作 . 以下是我们的经验(Node.js平台)的一些重要问题:
使用cron.yaml文件时,请确保您拥有最新的awsebcli,因为旧版本无法正常运行 .
创造新环境也至关重要(至少在我们的情况下是这样),而不仅仅是克隆旧环境 .
如果要确保EC2工作器层实例支持CRON,请将ssh插入其中(
eb ssh
),然后运行cat /var/log/aws-sqsd/default.log
. 它应报告为aws-sqsd 2.0 (2015-02-18)
. 如果您没有2.0版本,那么在创建环境时出现问题,您需要创建一个如上所述的新环境 .关于jamieb的响应,并且如alrdinleal所提到的,您可以使用'leader_only'属性来确保只有一个EC2实例运行cron作业 .
报价取自http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html:
我试图在我的eb上实现类似的东西,所以如果我解决它将更新我的帖子 .
UPDATE:
好吧,我现在使用以下eb配置工作cronjobs:
本质上,我使用cronjobs创建一个临时文件,然后将crontab设置为从临时文件中读取,然后删除临时文件 . 希望这个帮助 .
如上所述, Build 任何crontab配置的根本缺陷是它只在部署时发生 . 随着群集自动放大,然后退回,最好也是第一个关闭的服务器 . 此外,没有故障转移,对我来说这是至关重要的 .
我做了一些研究,然后与我们的AWS账户专家交谈,以反映想法并确认我提出的解决方案 . 你可以用OpsWorks完成这个,虽然它有点像用房子来杀死苍蝇 . 也可以使用Data Pipeline with Task Runner,但这在它可以执行的脚本中的能力有限,我需要能够运行PHP脚本,并可以访问整个代码库 . 您还可以在ElasticBeanstalk集群之外专用EC2实例,但之后您不会再进行故障转移 .
所以这就是我想出来的,这显然是非常规的(正如AWS代表评论的那样)并且可能被认为是一种黑客攻击,但它可以运行并且可以通过故障转移实现 . 我选择了使用SDK的编码解决方案,我将在PHP中展示,尽管您可以使用您喜欢的任何语言执行相同的方法 .
通过这个以及如何操作......你可以像往常一样在每个EC2实例上调用crontab中的脚本 . 每个脚本在开头都包含它(或者每个脚本包含一个文件,因为我使用它),它 Build 一个ElasticBeanstalk对象并检索所有实例的列表 . 它仅使用列表中的第一个服务器,并检查它是否与自身匹配,如果它继续,它将继续,否则它将死亡并关闭 . 我已经检查过并且返回的列表似乎是一致的,从技术上讲,它只需要一分钟左右一致,因为每个实例都执行预定的cron . 如果确实发生了变化,那就无所谓了,因为它只与那个小窗口有关 .
这并不优雅,但适合我们的特定需求 - 这不是通过额外服务增加成本或必须拥有专用的EC2实例,并且在发生任何故障时都会进行故障转移 . 我们的cron脚本运行维护脚本,这些脚本放入SQS,集群中的每个服务器都有助于执行 . 如果符合您的需求,至少可以为您提供备用选项 .
-Davey
我与AWS支持代理进行了交谈,这就是我们如何为我工作的方式 . 2015解决方案:
使用your_file_name.config在.ebextensions目录中创建一个文件 . 在配置文件输入中:
该解决方案有两个缺点:
在后续部署中,Beanstalk将现有的cron脚本重命名为.bak,但cron仍会运行它 . 你的Cron现在在同一台机器上执行两次 .
如果您的环境扩展,您将获得多个实例,所有实例都在运行您的cron脚本 . 这意味着您的邮件重复,或您的数据库存档重复
解决方法:
确保创建cron的任何.ebextensions脚本还会在后续部署中删除.bak文件 .
有一个帮助脚本,它执行以下操作: - 从元数据获取当前的实例ID - 从EC2标记获取当前的Auto Scaling组名称 - 获取该组中的EC2实例列表,按字母顺序排序 . - 从该列表中获取第一个实例 . - 将步骤1中的实例ID与步骤4中的第一个实例ID进行比较 . 然后,您的cron脚本可以使用此帮助程序脚本来确定它们是否应该执行 .
警告:
用于Beanstalk实例的IAM角色需要ec2:DescribeTags和autoscaling:DescribeAutoScalingGroups权限
从中选择的实例是Auto Scaling显示为InService的实例 . 这并不一定意味着它们已完全启动并准备好运行您的cron .
如果使用默认的beanstalk角色,则不必设置IAM角色 .
你真的不会有多个应用程序实例,这可能会导致竞争条件和其他奇怪的问题 . 我实际上recently blogged about this(页面上的第4或第5个提示) . 简短版本:根据应用程序,使用SQS等作业队列或iron.io等第三方解决方案 .
使用
files
而不是container_commands
的更易读的解决方案:请注意,格式与通常的crontab格式不同,它指定用户运行命令 .
有人想知道leader_only自动扩展新领导者出现时的问题 . 我似乎无法弄清楚如何回复他们的评论,但看到这个链接:http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
以下是该解决方案的完整说明:
http://blog.paulopoiati.com/2013/08/25/running-cron-in-elastic-beanstalk-auto-scaling-environment/
http://docs.aws.amazon.com/autoscaling/latest/userguide/as-instance-termination.html#instance-protection
我有另一个解决方案,如果需要通过cron运行php文件,如果你设置了任何NAT实例,那么你可以将cronjob放在NAT实例上并通过wget运行php文件 .
2017:如果您使用的是Laravel5
你只需要2分钟来配置它:
创建一个 Worker 层
安装laravel-aws-worker
composer require dusterio/laravel-aws-worker
就是这样!
现在将执行
App\Console\Kernel
中的所有任务详细说明和解释:https://github.com/dusterio/laravel-aws-worker
如何在Laravel中编写任务:https://laravel.com/docs/5.4/scheduling
所以我们一直在努力解决这个问题,在与AWS代表进行一些讨论后,我终于想出了我认为最好的解决方案 .
使用带有cron.yaml的工作层绝对是最容易解决的问题 . 但是,文档没有说清楚的是,这会将作业放在您可接受的SQS队列的末尾,因为它取决于队列的大小 . 一种选择是使用一个完全独立的环境来运行cron作业,但我认为这太过分了 .
其他一些选项,例如检查您是否是列表中的第一个实例,也不理想 . 如果当前的第一个实例正在关闭,该怎么办?
实例保护也可能带来问题 - 如果该实例被锁定/冻结该怎么办?
重要的是要了解AWS如何管理cron.yaml功能 . 有一个SQS守护进程使用Dynamo表来处理“领导者选举” . 它经常写入此表,如果当前的领导者在短时间内没有写入,则下一个实例将接管为领导者 . 这是守护进程决定将作业触发到SQS队列的实例 .
我们可以重新利用现有功能,而不是尝试重写我们自己的功能 . 你可以在这里看到完整的解决方案:https://gist.github.com/dorner/4517fe2b8c79ccb3971084ec28267f27
这是在Ruby中,但您可以轻松地将其适用于具有AWS SDK的任何其他语言 . 从本质上讲,它检查当前的领导者,然后检查状态以确保它处于良好状态 . 它将循环直到当前领导者处于良好状态,并且如果当前实例是领导者,则执行该作业 .
这是一个修复,你想在PHP中这样做 . 你只需要在.ebextensions文件夹中使用cronjob.config就可以让它像这样工作 .
envvars获取文件的环境变量 . 您可以像上面那样在tmp / sendemail.log上调试输出 .
希望这有助于某人,因为它肯定帮助了我们!
我对2018年的1美分贡献
这是正确的方法(使用
django/python
和django_crontab
app):在
.ebextensions
文件夹里面创建一个像这样的文件98_cron.config
:它必须是
container_commands
而不是commands