Amazon Linux 2 AMI 上的命令 01_migrate 失败
Posted
技术标签:
【中文标题】Amazon Linux 2 AMI 上的命令 01_migrate 失败【英文标题】:Command 01_migrate failed on Amazon Linux 2 AMI 【发布时间】:2020-10-19 06:56:57 【问题描述】:我有一个部署到 Elastic Beanstalk Amazon Linux 2 AMI 的 Django 项目。我安装了 Pymysql 以连接到数据库,并将这些行添加到 settings.py 中,如下所示;
import pymysql
pymysql.version_info = (1, 4, 6, "final", 0)
pymysql.install_as_MySQLdb()
我还有一个用于迁移数据库的 .config 文件;
container_commands:
01_migrate:
command: "django-admin.py migrate"
leader_only: true
option_settings:
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: mysite.settings
通常,我在我的 Linux AMI 上使用 mysqlclient
和这个 .config 文件,但它在 Linux 2 AMI 上不起作用,所以我安装了 PyMySQL。现在,我正在尝试部署我的项目的更新版本,但出现如下错误;
Traceback (most recent call last):
File "/opt/aws/bin/cfn-init", line 171, in <module>
worklog.build(metadata, configSets)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 129, in build
Contractor(metadata).build(configSets, self)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 530, in build
self.run_config(config, worklog)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 542, in run_config
CloudFormationCarpenter(config, self._auth_config).build(worklog)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/construction.py", line 260, in build
changes['commands'] = CommandTool().apply(self._config.commands)
File "/usr/lib/python2.7/site-packages/cfnbootstrap/command_tool.py", line 117, in apply
raise ToolError(u"Command %s failed" % name)
ToolError: Command 01_migrate failed
我该如何解决这个问题?
【问题讨论】:
当您从实例手动运行django-admin.py migrate
时,它是否按预期工作?
当我在我的 powershell 上运行命令时,它按预期工作。我可以将更改迁移到我的数据库。
很好,但是当您 ssh 进入 EB 实例并运行命令时,它是否可以在 EB 实例本身上工作?
我尝试运行 migrate 命令,但出现No such file or directory
之类的错误
django-admin.py migrate
来自哪里?它是您的应用程序的一部分,还是某些依赖项?
【参考方案1】:
Amazon Linux 2 的设置与 AL1 完全不同,截至 2020 年 7 月 24 日的当前文档已过时。 django-admin
beanstalk 安装的环境似乎不在路径上,因此您可以源环境来激活并确保它是。
我也留下了我的答案here,其中更详细地说明了我是如何得出这个答案的,但解决方案(我不喜欢)是:
container_commands:
01_migrate:
command: "source /var/app/venv/*/bin/activate && python3 manage.py migrate"
leader_only: true
尽管我不喜欢它,但我已通过 AWS Support 验证这实际上是推荐的方法。您必须获取 python 环境,就像 AL2 一样,他们使用虚拟环境来保持更加一致。
【讨论】:
请注意,这会激活正确的 python(设置 PATH),但不会激活 EBS UI 设置的环境值。如果 dango 使用其中任何一个(凭证 BAD、秘密名称等),则不会为迁移命令设置它。 这个命令依赖于(至少对我而言)我在 GUI 中为一些秘密设置的环境变量,它工作得很好。我不确定你的意思@MatanDrory 这很奇怪。我刚刚在我的 EBS 创建的 EC2 机器上对其进行了测试。我运行printenv
并没有看到我的环境变量,然后运行source /var/app/venv/*/bin/activate && printenv
并再次我没有看到环境变量,唯一的变化是在PATH 中。我目前有一个丑陋的解决方法,它使用一个 prebuild hook 将 env 文件复制为导出格式,我改为使用它。问题在于“/opt/elasticbeanstalk/deployment/env”中的 env 文件仅在成功部署后才创建,迫使我从示例应用程序开始【参考方案2】:
answer from @nick-brady 很棒,它提供了基本的解决方案。
但是,migrating to Amazon Linux 2 上的 AWS 文档建议我们应该使用 .platform
钩子来做这样的事情:
我们建议使用平台挂钩在您的环境实例上运行自定义代码。您仍然可以在
.ebextensions
配置文件中使用命令和容器命令,但它们并不容易使用。例如,在 YAML 文件中编写命令脚本可能很麻烦且难以测试。
来自AWS Knowledge Center:
...最好使用平台挂钩,而不是在
.ebextension
配置文件中提供文件和命令。
作为奖励,平台挂钩的输出被收集在一个单独的日志文件 (/var/log/eb-hooks.log
) 中,默认情况下该文件包含在 bundle 和 tail 日志中。这使得调试更容易一些。
基本思想是在您的应用程序源包中创建一个 shell 脚本,例如.platform/hooks/postdeploy/01_django_migrate.sh
。这在docs for extending EB linux platforms 的平台挂钩部分中有更详细的描述。
文件必须是可执行的,所以:chmod +x .platform/hooks/postdeploy/01_django_migrate.sh
文件内容可能如下所示(基于@nick-brady's answer):
#!/bin/bash
source "$PYTHONPATH/activate" &&
# log which migrations have already been applied
python manage.py showmigrations;
# migrate
python manage.py migrate --noinput;
collectstatic
等也可以这样做。
请注意,Python 虚拟环境的路径可作为环境变量PYTHONPATH
用于平台挂钩。您可以通过检查实例上的文件 /opt/elasticbeanstalk/deployment/env
来验证这一点,例如通过 ssh。另见AWS knowledge center。
对于那些想知道的人,shell 脚本中的&&
是一种条件执行:只有在前面成功的情况下才执行以下操作。
参见例如here.
仅限领导
在部署期间,应该有一个EB_IS_COMMAND_LEADER
环境变量,可以对其进行测试,以便在.platform
挂钩中实现leader_only
行为(基于this post):
...
if [[ $EB_IS_COMMAND_LEADER == "true" ]];
then
python manage.py migrate --noinput;
python manage.py collectstatic --noinput;
else
echo "this instance is NOT the leader";
fi
...
【讨论】:
有没有办法像在命令中那样知道这是否是领导者?我更喜欢这个解决方案,因为环境变量是可访问的(我没有测试过,但我看到你正在使用 $PYTHONPATH)。唯一的问题是我宁愿迁移只在领导者上运行。 @MatanDrory:对此不确定。我无法在文档中找到任何明确的内容,我自己也没有尝试过。看起来您仍然可以在 .ebextensions 中使用leader_only
,或者在您的 .platform 脚本中使用测试实现类似的效果(还要注意 hooks and config-hooks 之间的区别)。
@MatanDrory:我找到了答案:在部署期间,您可以检查一个名为 EB_IS_COMMAND_LEADER
的环境属性,如this post 中所述。我会更新答案。
注意:要在登录实例时激活python(例如通过eb ssh
),可以使用get_config
工具获取PYTHONPATH
的值:source "$(/opt/elasticbeanstalk/bin/get-config environment -k PYTHONPATH)/activate"
【参考方案3】:
在我的情况下,这个 .config 工作
container_commands: 01_迁移: 命令:“django-admin.py 迁移” 仅领导者:真 02_collectstatic: 命令:“django-admin.py collectstatic --noinput”
我有这个命令:“source /var/app/venv/*/bin/activate && python3 manage.py config 直到 1 月 4 日,突然我遇到了部署错误
【讨论】:
以上是关于Amazon Linux 2 AMI 上的命令 01_migrate 失败的主要内容,如果未能解决你的问题,请参考以下文章
sh EC2上的Amazon Linux AMI 2017.09.0(HVM)上的golang,docker和docker-compose的安装脚本
Amazon Linux AMI 上的“bash: jstack: command not found”错误
如何在 AWS 上的 Amazon Linux AMI 中自动启动 node.js 应用程序?
将带有 Sinatra 2.0.0beta2 的 Rails 5 应用程序部署到 Amazon Linux AMI 时出错