用户数据脚本未在我的自定义 AMI 上运行,但在标准 Amazon linux 中运行

Posted

技术标签:

【中文标题】用户数据脚本未在我的自定义 AMI 上运行,但在标准 Amazon linux 中运行【英文标题】:User-data scripts is not running on my custom AMI, but working in standard Amazon linux 【发布时间】:2015-01-21 02:11:07 【问题描述】:

这几天我搜索了很多关于“user-data script is not working”的话题,但是直到现在我还没有对我的情况有任何了解,请帮我弄清楚发生了什么,谢谢很多!

根据AWSUser-data解释:

当您在 Amazon EC2 中启动实例时,您可以选择将用户数据传递给实例,这些数据可用于执行常见的自动化配置任务,甚至在实例启动后运行脚本。

所以我尝试在实例启动时传递我自己的用户数据,这是我的用户数据:

\#!/bin/bash

echo 'test' > /home/ec2-user/user-script-output.txt

但是这个路径下没有文件:/home/ec2-user/user-script-output.txt

我检查了/var/lib/cloud/instance/user-data.txt,该文件存在并且与我的用户数据脚本相同。

另外我检查了/var/log/cloud-init.log的登录,没有错误信息。

但是如果我使用 Amazon linux(2014.09.01) 启动一个新实例,用户数据脚本就可以工作,但我不确定我的 AMI(基于 Amazon linux)和 Amazon linux 之间有什么区别。

我看到的唯一不同的部分是如果我运行这个脚本:

sudo yum list installed | grep cloud-init

我的 AMI:

cloud-init.noarch 0.7.2-8.33.amzn1 @amzn-main

亚马逊 Linux:

cloud-init.noarch 0.7.2-8.33.amzn1 已安装

我不确定是不是这个原因?

如果您需要更多信息,我很乐意提供,请告诉我在我自己的 AMI 中发生了什么以及如何修复它?

非常感谢

更新

刚刚从这个post找到答案,

如果我在用户数据文件的顶部添加#cloud-boothook,它会起作用!

#cloud-boothook
#!/bin/bash
echo 'test' > /home/ec2-user/user-script-output.txt

但仍然不知道为什么。

【问题讨论】:

How to make EC2 user-data work on freshly built AMI, made with Packer的可能重复 #cloud-boothook 解决方案对我不起作用。 UserData 仍未运行。 现在有一个官方文档页面。经过所有的尝试,这终于对我有用了。aws.amazon.com/premiumsupport/knowledge-center/… 【参考方案1】:

User_data 仅在第一次启动时运行。由于您的图像是自定义图像,我想它已经启动过一次,因此 user_data 已停用。

对于 Windows,可以通过选中 Ec2 Services Properties 中的框来完成。我正在研究如何在自定义图像创建结束时以自动方式执行此操作。

对于linux,我想机制是一样的,需要在你的自定义镜像上重新激活user_data。

#cloud-boothook 使其工作,因为它将脚本从 user_data 机制更改为 cloud-boothook 机制,每次启动都会运行。


编辑:

这是使用 powershell 在 windows 上重新激活启动的代码:

$configFile = "C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\Config.xml"
[xml] $xdoc = get-content $configFile
$xdoc.SelectNodes("//Plugin") |? $_.Name -eq "Ec2HandleUserData" |% $_.State = "Enabled" 
$xdoc.SelectNodes("//Plugin") |? $_.Name -eq "Ec2SetComputerName" |% $_.State = "Enabled" 
$xdoc.OuterXml | Out-File -Encoding UTF8 $configFile

$configFile = "C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\BundleConfig.xml"
[xml] $xdoc = get-content $configFile
$xdoc.SelectNodes("//Property") |? $_.Name -eq "AutoSysprep" |% $_.Value = "Yes" 
$xdoc.OuterXml | Out-File -Encoding UTF8 $configFile

(我知道问题集中在 linux,但它可以帮助其他人......)

【讨论】:

【参考方案2】:

正如我测试的那样,/var/lib/cloud 目录中有一些引导数据。 清除该目录后,用户数据脚本正常工作。

rm -rf /var/lib/cloud/*

【讨论】:

【参考方案3】:

我在 Ubuntu 16.04 hvm AMI 上也遇到了同样的问题。我已将问题提交给 AWS 支持,但我仍然找不到影响它的确切原因/错误。

但我仍有一些东西可以帮助你。

在使用 AMI 之前删除 /var/lib/cloud 目录(每次)。然后在创建 Image 时,将其设置为 no-reboot。

如果这些方法仍然不起作用,您可以通过强制用户数据手动运行来进一步测试它。还有 tailf /var/log/cloud-init-output.log 用于 cloud-init 状态。它应该以 modules:final 之类的东西结尾,以使您的用户数据运行。它不应该停留在 modules:config 上。

sudo rm -rf /var/lib/cloud/* sudo cloud-init init sudo cloud-init modules -m final

我不太清楚上述命令是否可以在 CentOS 上运行。我已经在 Ubuntu 上测试过了。

就我而言,我也尝试过删除 /var/lib/cloud 目录,但在我们的场景中仍然无法执行用户数据。但我想出了不同的解决方案。我们所做的是我们使用上述命令创建了脚本,并让该脚本在系统启动时运行。

我在 /etc/rc.local 中添加了以下行来实现它。

sudo bash /home/ubuntu/force-user-data.sh || exit 1

但这里有个问题,它会在每次启动时执行脚本,这样您的用户数据就会在每次启动时运行,就像 #cloud-boothook 一样。不用担心,您可以通过在最后删除 force-user-data.sh 本身来调整它。所以你的 force-user-data.sh 看起来像

#!/bin/bash sudo rm -rf /var/lib/cloud/* sudo cloud-init init sudo cloud-init modules -m final sudo rm -f /home/ubuntu/force-user-data.sh exit 0

如果有人能说明为什么它无法执行用户数据,我将不胜感激。

【讨论】:

太棒了。你为我节省了很多时间!【参考方案4】:

以答案为例:确保标题中只有#!/bin/bash

#!/bin/bash
yum update -y
yum install httpd mod_ssl
service httpd start
chkconfig httpd on

【讨论】:

【参考方案5】:

我在这方面遇到了很多麻烦。我将提供详细的演练。

另外一个问题是我使用 terraform 通过启动配置和自动缩放组来实例化主机。

我无法通过在 lc.tf 中添加内联脚本来使其工作

user_data                   = DATA <<
"
#cloud-boothook
#!/bin/bash
echo 'some crap'\'
"
DATA

我可以从用户数据中获取它,

wget http://169.254.169.254/latest/user-data

但注意到我得到它时仍然包含引号。

这就是我让它工作的方式:我改为从模板中提取它,因为所见即所得。

user_data                   = "$data.template_file.bootscript.rendered"

这意味着我还需要像这样声明我的模板文件:

data "template_file" "bootscript" 
  template = "$file("bootscript.tpl")"


但我仍然在云初始化日志中收到错误 /var/log/cloud-init.log [警告]:未处理的非多部分(文本/x-not-multipart)用户数据:'Content-Type: text/cloud...'

然后我找到了this article about user data formatting user,这是有道理的,如果用户数据可以分为多个部分,也许 cloud-init 需要 cloud-init 命令在一个地方,而脚本在另一个地方。

所以我的 bootscript.tpl 看起来像这样:

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
echo "some crap"
--//

【讨论】:

【参考方案6】:

在 ubuntu 16 上,删除 /var/lib/cloud/* 不起作用。我只从文件夹 /var/lib/cloud/ 中删除了实例,然后它对我来说运行良好

我跑了:

sudo rm /var/lib/cloud/instance
sudo rm /var/lib/cloud/instances

然后我重试了我的用户数据脚本,它运行良好

【讨论】:

这在 Ubuntu 上对我有用,但我需要运行 sudo rm -r /var/lib/cloud/instances,因为 instances 是一个目录。【参考方案7】:

我使用的是 CentOS,用户数据的逻辑很简单:

在文件 /etc/rc.local 中有一个对 initial.sh 脚本的调用,但它首先查找一个标志:

if [ -f /var/tmp/initial ]; then
    /var/tmp/initial.sh &
fi

initial.sh 是执行用户数据的文件,但最后它删除了标志。因此,如果您希望新的 AMI 再次执行用户数据,只需在创建映像之前再次创建标志:

touch /var/tmp/initial

【讨论】:

【参考方案8】:

只需在用户数据脚本的末尾添加 --// 即可,例如:

#!/bin/bash
#Upgrade ec2 instance
sudo yum update -y 

#Start docker service 
sudo service docker start 

 --//

【讨论】:

你能解释一下这是做什么的吗?【参考方案9】:

用户数据应该可以在不使用#cloud-boothook(用于在启动过程中尽早激活用户数据)的情况下正常执行。

我启动了一个新的 Amazon Linux AMI 并使用了您的用户数据,以及一些额外的:

#!/bin/bash

echo 'bar' > /tmp/bar
echo 'test' > /home/ec2-user/user-script-output.txt
echo 'foo' > /tmp/foo

这成功创建了三个文件。

用户数据脚本以root 执行,因此它应该有权在任何位置创建文件。

我注意到在您提供的代码中,一个示例引用了/home/ec2-user/user-script/output.txt(带有子目录),一个示例引用了/home/ec2-user/user-script-output.txt(没有子目录)。如果您尝试在不存在的目录中创建文件,该命令会失败,这是可以理解的,但您的“更新”示例似乎表明它确实有效。

【讨论】:

感谢您的回答,对此感到抱歉,/home/ec2-user/user-script/output.txt 是错字,已经修复,现在我仍然不知道为什么它没有如果我删除#cloud-boothook 将无法正常工作,但仍在尝试解决【参考方案10】:

!/bin/bash

不要在行首留下任何空白。使用确切的命令。否则它可能会在 AMAZON Linux AMI 中运行,但不会在 RHEL 中运行。

【讨论】:

【参考方案11】:

我让它工作的唯一方法是在 #!/bin/bash 之前添加 #cloud-boothook

这是一个典型的用户数据脚本,用于在新创建的实例上安装 Apache Web 服务器

#cloud-boothook
#!/bin/bash

yum update -y 
yum install -y httpd.x86_64 
systemctl start httpd.service 
systemctl enable httpd.service 

没有#cloud-boothook 它不起作用,但有了它,它就可以工作。似乎不同的用户有不同的体验。有些人可以在没有它的情况下让它工作,不知道为什么。

【讨论】:

【参考方案12】:

另外, 如果我们使用像

这样的用户交互命令
sudo yum install java-1.8.0-devel

然后,我们需要使用 -y 之类的标志

sudo yum install java-1.8.0-devel -y

您可以在 EC2 文档的 Run commands at launch 下找到此内容。

参考:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-shell-scripts

【讨论】:

以上是关于用户数据脚本未在我的自定义 AMI 上运行,但在标准 Amazon linux 中运行的主要内容,如果未能解决你的问题,请参考以下文章

属性或方法“sendResetMail”未在实例上定义,但在渲染期间引用

使用React Native的Firebase查询未在我的屏幕上显示(但在console.log上显示)

TFS Api 未在 Dev Azure 上的自定义流程模板中提供自定义状态

Vue.js 属性或方法“选项”未在实例上定义,但在渲染期间被引用

带有自定义声音的推送通知未在 iOS 中显示

UITableViewCell 自定义按钮图像未在 Swift 3 中更新