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

这几天我搜索了很多关于“用户数据脚本不起作用”的话题,但到现在为止,我还没有得到任何关于我的情况,请帮助我弄清楚发生了什么,非常感谢!

根据 AWS 用户资料的解释:

在 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.诺亚0.7.2-8.33。Amzn1@amzn-main

亚马逊 linux:

Cloud-init.诺亚0.7.2-8.33。安装了 amzn1

我不确定这就是原因?

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

非常感谢

更新

刚从这个 邮寄上找到了答案,

如果我在用户数据文件的顶部添加 # cloud-boothook,它就可以工作了!

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

但还是不知道为什么。

75445 次浏览

User Data 应该在不使用 #cloud-boothook(用于在引导过程中尽早激活 User Data)的情况下正常执行。

我创建了一个新的 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(没有子目录)。如果您试图在一个不存在的目录中创建一个文件,这个命令可能会失败,这是可以理解的,但是您的“ Update”示例似乎表明它确实可以工作。

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

rm -rf /var/lib/cloud/*

User _ data 仅在第一次启动时运行。由于您的映像是自定义的,因此我认为它已经启动过一次,因此 user _ data 将被禁用。

对于窗口,可以通过选中 Ec2服务属性中的一个复选框来完成。我正在研究如何在自定义图像创建结束时自动完成这项工作。

对于 linux,我假设机制是相同的,并且需要在自定义映像上重新激活 user _ data。

#cloud-boothook之所以能够工作,是因为它将脚本从 user_data机制更改为在每次启动时运行的 云图书机制。


编辑:

下面是使用 powershell 重新激活窗口启动的代码:

$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,但它可以帮助其他人...)

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

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

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

initial.sh is the file that does the execution of user-data, but in the end it deletes the flag. So, if you want your new AMI to execute user-data again, just create the flag again before create the image:

touch /var/tmp/initial

我在 Ubuntu 16.04 hvm AMI 上也遇到过同样的问题。我已经向 AWS 支持提出了这个问题,但是仍然找不到影响它的确切原因/bug。

但我还是有些东西可以帮到你。

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

如果这些东西仍然不能工作,您可以通过强制用户数据手动运行来进一步测试它。对于云初始化状态,还需要使用 /var/log/cloud-init-output.log。它应该以模块之类的东西结束: final 以使您的用户数据运行。它不应该停留在模块上: config。

Sudo rm-rf/var/lib/cloud/* Sudo cloud-init init Sudo cloud-init 模块 -m final

我不太清楚上面的命令是否能在 CentOS 上工作,我已经在 Ubuntu 上测试过了。

在我的示例中,我还尝试删除/var/lib/cloud 目录,但仍然无法在我们的场景中执行用户数据。但我想出了不同的解决办法。我们所做的就是使用上面的命令创建脚本,并在系统引导时运行该脚本。

我在/etc/rc.local 中添加了以下代码行来实现这一点。

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

但是这里有一个问题,它将在每次引导时执行脚本,这将使您的用户数据在每次引导时运行,就像 # cloud-boothook 一样。不用担心,只要删除强制用户数据就可以对其进行调整。在结束的时候自己。所以你的武力-用户-数据。她看起来就像

# !/bin/bash Sudo rm-rf/var/lib/cloud/* Sudo cloud-init init Sudo cloud-init 模块 -m final Sudo rm-f/home/ubuntu/ force-user-data.sh 0号出口

如果有人能给我解释一下为什么它不能执行用户数据,我将非常感激。

我在这方面遇到了很多麻烦,不过我会提供详细的步行路线。

我额外的问题是,我正在使用 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 [警告] : 未处理的非多部分(text/x-not-multipart)用户数据: ‘ Content-Type: text/cloud...’

然后我发现了 本文介绍用户数据格式化用户这是有道理的,如果用户数据可以分成多个部分,那么 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"
--//

这就是答案作为一个例子: 确保你在标题中只有 #!/bin/bash

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

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

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

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

#cloud-boothook
#!/bin/bash


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

如果没有 # Cloud-boobook,它就不能工作,但是有了它,它就可以工作。似乎不同的用户有不同的体验。有些人不用它也能工作,不知道为什么。

还有, 如果我们使用用户交互命令,如

sudo yum install java-1.8.0-devel

然后,我们需要与 -y 这样的标志一起使用

sudo yum install java-1.8.0-devel -y

您可以在启动时 Run 命令下的 EC2文档中找到这一点。

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

在 ubuntu 16上,删除/var/lib/cloud/* 不起作用。我只从/var/lib/cloud/文件夹中删除了一些实例,然后它就可以正常运行了

我跑过去:

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

然后我重试了我的用户数据脚本,它工作得很好

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

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


#Start docker service
sudo service docker start


--//