如何在自定义 FreeBSD AMI 上运行用户数据脚本?

如何在自定义 FreeBSD AMI 上运行用户数据脚本?

我读到您只能在 EC2 AMI 上运行一次 userdata。如果您从 EC2 实例创建自定义 AMI,则无法在该自定义 AMI 上运行 userdata 脚本。在 Ubuntu 实例上,您可以删除 /var/lib/cloud/* ,创建自定义 AMI 并在自定义 AMI 上运行 userdata。我在 FreeBSD 上找不到 /var/lib/cloud/* 的等效项。

有没有办法在自定义 FreeBSD AMI 上运行 userdata 或创建 AMI 的替代方法,以便您可以再次运行 userdata 脚本?

Linux 有#cloud-boothook,但对于 FreeBSD,我只找到了 configinit,它不能满足我的需要。我们在启动实例时将参数从命令行传递到用户数据脚本中。

答案1

AWS 上的 FreeBSD AMI 不提供与其他 AMI 相同级别的 user_data 脚本支持。正如您所指出的,它不支持#cloud-boothookuser_data 并且忽略启动后传递的任何 user_data。

一个简单的解决方案如下:

sed -i '' '/KEYWORD: *firstboot$/d' /usr/local/etc/rc.d/ec2_configinit

这是一个 hack——您的实例现在将执行所有 user_data 脚本,甚至是那些没有标签的脚本#cloud-boothook,但在我看来,它比脚本的默认行为要好得多。请注意,人们始终可以ec2_configinit通过在/etc/rc.conf.

答案2

我提供我自己的答案,因为接受的答案非常粗糙。

更新:我认为接受的答案非常粗糙,但最终我还是使用它因为它最适合我。这里的其余部分只是提供一些可能对某些人有用的额外背景。接受的答案最终最适合我,因为:(1)它允许我始终执行 shell 脚本,(2)除了按照我在下面解释的方式处理用户数据文件之外,它不执行任何其他操作,( 3)如果我愿意,我仍然可以在 rc.conf 中禁用它。

问题是,即使在 Amazon Linux 上,用户数据脚本也仅在首次启动时执行,除非您使用 MIME 多部分/混合技巧。你可以查查看https://cloudinit.readthedocs.io/en/latest/topics/format.html但我举了一个突破极限的例子:

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

--schnipp-schnapp
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]

--schnipp-schnapp
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="user-data.sh"

#!/bin/bash
echo "Hello World." >> /etc/motd

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

#!/bin/bash
echo "Kilroy was here." >> /etc/motd

--schnipp-schnapp
Content-Type: image/jpeg
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="imput64-8503-small.jpg"

/9j/4AAQSkZJRgABAQEAlgCWAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcU
FhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgo
...
JFSUkfQjjHr9yT2T9SSSdLS15R/qM64pbLRUcsExOk6axzpxhiQATFSDIB6E68K/c6WlrzEoTypl
JoceL9zq7NbXis8oopa6RRNUQovmNlCM5IIzxQLkgkD0wQCAFLYaXzKkSSVEkzOZXqJJOUjsfXkf
cknJOMk++lpa9u+AGkJwsuJACiqCeJGm5pJiZJXBr4Sx04IfzZiS3I9r3/TQakADkD260tLWjxQk
hE9/tVFgPm8K/9k=

--schnipp-schnapp--

我发现这两个脚本是按字母顺序执行的,而图像部分被忽略了。

除非 FreeBSD AMI 维护者实现这个多部分内容及其涉及的所有内容

  • 文本/云引导
  • 文本/云配置
  • 文本/云配置存档
  • 文/jinja2
  • 文本/部分处理程序
  • 文/新贵工作
  • 文本/x-include-once-url
  • 文本/x-include-url
  • 文本/x-shell脚本

为什么您希望 ec2-cloudinit 执行的所有其他操作始终像这样执行?最终你只能靠自己了。

自己获取用户数据并决定如何处理它确实没有什么坏处。以下是获取它的方法:

fetch -q -o - http://169.254.169.254/latest/user-data

所以,如果你想执行它,你可以将它放入 rc.local 中:

fetch -q -o - http://169.254.169.254/latest/user-data |sh 

或者

fetch -q -o /tmp/user-data.sh http://169.254.169.254/latest/user-data
mkdir 700 /tmp/user-data.sh
/tmp/user-data.sh

真的没什么大不了的。不确定支持复杂的多部分结构是否值得。 FreeBSD AMI 的做法非常不同,而且更简单,而且可以说还不错。

  • 如果它以 hash-bang #! 开头它将被保存并执行
  • 如果它以“">/var/tmp/here”开头,它将被写入指定的目的地
  • 如果它以“>>/var/tmp/here”开头,它将被附加到如此指定的目的地
  • 否则,它将被视为 shell 脚本的未压缩 tar 存档,进行扩展,然后使用上述规则执行每个文件。

因为它不是 AWS 标准,所以我不会理会它。只需有一个脚本并强制它在 rc.local 中执行,或者甚至不执行,只是检查以找到以某种方式控制行为的参数。

相关内容