我有一个基于Amazon Linux AMI运行AMI的EC2实例。与所有此类AMI一样,它支持cloud-init系统,用于根据传递到每个实例的用户数据运行启动脚本。在这种特殊情况下,我的用户数据输入恰好是包含几个其他启动脚本的Include文件:
#include
http://s3.amazonaws.com/path/to/script/1
http://s3.amazonaws.com/path/to/script/2
我第一次启动实例时,cloud-init启动脚本正确运行。但是,如果我对实例进行软重启(例如,通过运行sudo shutdown -r now
),实例将在中重新启动,而不会第二次运行启动脚本。如果我进入系统日志,我可以看到:
Running cloud-init user-scripts
user-scripts already ran once-per-instance
[ OK ]
这不是我想要的 - 我可以看到启动脚本每个实例生命周期只运行一次的实用程序,但在我的情况下,这些应该在每次实例启动时运行,就像正常的启动脚本一样。
我意识到一种可能的解决方案是在第一次运行后手动让我的脚本插入rc.local
。然而,这似乎很麻烦,因为cloud-init和rc.d环境略有不同,我现在必须分别在首次启动和所有后续启动时调试脚本。
有谁知道如何告诉cloud-init始终运行我的脚本?这听起来像是cloud-init的设计者会考虑的事情。
答案 0 :(得分:51)
在11.10,12.04及更高版本中,您可以通过让'scripts-user''始终'运行来实现这一目标。 在/etc/cloud/cloud.cfg中你会看到类似的东西:
cloud_final_modules:
- rightscale_userdata
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
- keys-to-console
- phone-home
- final-message
这可以在启动后修改,或者可以通过用户数据插入覆盖此节的cloud-config数据。即,在您可以提供的用户数据中:
#cloud-config
cloud_final_modules:
- rightscale_userdata
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- [scripts-user, always]
- keys-to-console
- phone-home
- final-message
这也可以像你在描述中所做的那样'#included'。 不幸的是,现在,你无法修改'cloud_final_modules',但只能覆盖它。我希望在某些时候添加修改配置部分的功能。
在cloud-config doc中有更多相关信息 http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/doc/examples/cloud-config.txt
或者,您可以将文件放在/ var / lib / cloud / scripts / per-boot中,它们将由'scripts-per-boot'路径运行。
答案 1 :(得分:19)
在/etc/init.d/cloud-init-user-scripts
中,修改此行:
/usr/bin/cloud-init-run-module once-per-instance user-scripts execute run-parts ${SCRIPT_DIR} >/dev/null && success || failure
到
/usr/bin/cloud-init-run-module always user-scripts execute run-parts ${SCRIPT_DIR} >/dev/null && success || failure
祝你好运!
答案 2 :(得分:7)
有一种可能性,虽然有些苛刻,但是删除了cloud-init用来确定用户脚本是否已经运行的锁定文件。在我的案例中(Amazon Linux AMI),此锁定文件位于/var/lib/cloud/sem/
中,并命名为user-scripts.i-7f3f1d11
(最后的哈希部分会在每次启动时更改)。因此,添加到Include文件末尾的以下用户数据脚本将起到作用:
#!/bin/sh
rm /var/lib/cloud/sem/user-scripts.*
我不确定这是否会对其他任何事情产生任何不利影响,但它在我的实验中有效。
答案 3 :(得分:7)
cloud-init现在支持本地,请参阅文档(http://cloudinit.readthedocs.io/en/latest/topics/examples.html#run-commands-on-first-boot)中的runcmd vs bootcmd命令说明:
“RUNCMD”:
#cloud-config
# boot commands
# default: none
# this is very similar to runcmd, but commands run very early
# in the boot process, only slightly after a 'boothook' would run.
# bootcmd should really only be used for things that could not be
# done later in the boot process. bootcmd is very much like
# boothook, but possibly with more friendly.
# - bootcmd will run on every boot
# - the INSTANCE_ID variable will be set to the current instance id.
# - you can use 'cloud-init-per' command to help only run once
bootcmd:
- echo 192.168.1.130 us.archive.ubuntu.com >> /etc/hosts
- [ cloud-init-per, once, mymkfs, mkfs, /dev/vdb ]
“bootcmd”:
Usage: cloud-init-per frequency name cmd [ arg1 [ arg2 [ ... ] ]
run cmd with arguments provided.
This utility can make it easier to use boothooks or bootcmd
on a per "once" or "always" basis.
If frequency is:
* once: run only once (do not re-run for new instance-id)
* instance: run only the first boot for a given instance-id
* always: run every boot
还要注意bootcmd中的“cloud-init-per”命令示例。从它的帮助:
{{1}}
答案 4 :(得分:0)
我在这个问题上挣扎了近两天,尝试了我能找到的所有解决方案,最后结合了几种方法,提出了以下内容:
-f file
这是DynamoDb跨区域复制过程的设置。
答案 5 :(得分:0)
另一种方法是在用户数据脚本中使用#cloud-boothook
。来自docs:
Cloud Boothook
- 从#cloud-boothook或Content-Type开始:text / cloud-boothook。
- 此内容是展位数据。它存储在/ var / lib / cloud下的文件中,然后立即执行。
- 这是最早可用的“挂钩”。 没有提供只能运行一次的机制。亭子必须注意 这本身。在环境中提供了实例ID 变量INSTANCE_ID。使用此变量提供一次实例 布告集数据集。
答案 6 :(得分:-1)
请在bash脚本上方使用以下脚本。
示例:在此处向您的文件打印问候世界
在添加到用户数据之前停止实例
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
/bin/echo "Hello World." >> /var/tmp/sdksdfjsdlf
--//