每当我的EC2实例启动时,如何让云启动启动脚本运行?
我有一个基于Amazon Linux AMI运行AMI的EC2实例。 像所有这样的AMI一样,它支持cloud-init系统根据传入每个实例的用户数据来运行启动脚本。 在这种特殊情况下,我的用户数据input恰好是一个包含多个其他启动脚本的Include文件:
#include http://s3.amazonaws.com/path/to/script/1 http://s3.amazonaws.com/path/to/script/2
第一次启动我的实例时,cloud-init启动脚本正确运行。 但是,如果我对该实例进行软重启(例如, sudo shutdown -r now
通过运行sudo shutdown -r now
),则实例会重新启动, 而不会再次运行启动脚本。 如果我进入系统日志,我可以看到:
Running cloud-init user-scripts user-scripts already ran once-per-instance [ OK ]
这不是我想要的 – 我可以看到启动脚本只在每个实例生命周期中运行一次的实用程序,但在我的情况下,每次启动实例时都应该运行,就像正常的启动脚本一样。
我意识到一个可能的解决scheme是手动让我的脚本在第一次运行后插入到rc.local
。 然而,这看起来很麻烦,因为cloud-init和rc.d环境略有不同,我现在必须在第一次启动和所有后续启动时分别debugging脚本。
有谁知道我可以告诉cloud-init总是运行我的脚本? 这听起来像是cloud-init的devise师会考虑的事情。
在11.10,12.04和更高版本中,可以通过使'scripts-user'运行'always'来实现这一点。 在/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
这也可以像您在描述中所做的那样“包含”。 不幸的是,现在,你不能修改“cloud_final_modules”,只能覆盖它。 我希望增加修改configuration部分的function。
或者,您可以将文件放在/ var / lib / cloud / scripts / per-boot中,然后以“scripts-per-boot”path运行。
在/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
祝你好运 !
有一种可能性,虽然有些骇人听闻,但是要删除cloud-init用来确定用户脚本是否已经运行的locking文件。 在我的情况下(Amazon Linux AMI),这个锁文件位于/var/lib/cloud/sem/
,名为user-scripts.i-7f3f1d11
(最后的哈希部分每次启动都会更改)。 因此,将以下用户数据脚本添加到“包含”文件的末尾将会有所诀窍:
#!/bin/sh rm /var/lib/cloud/sem/user-scripts.*
我不确定这是否会对其他方面产生任何不利影响,但在我的实验中有效。
cloud-init现在支持它,请参阅文档中的runcmd vs bootcmd命令描述( http://cloudinit.readthedocs.io/en/latest/topics/examples.html#run-commands-on-first-boot ):
“RUNCMD”:
#cloud-config # run commands # default: none # runcmd contains a list of either lists or a string # each item will be executed in order at rc.local like level with # output to the console # - runcmd only runs during the first boot # - if the item is a list, the items will be properly executed as if # passed to execve(3) (with the first arg as the command). # - if the item is a string, it will be simply written to the file and # will be interpreted by 'sh' # # Note, that the list has to be proper yaml, so you have to quote # any characters yaml would eat (':' can be problematic) runcmd: - [ ls, -l, / ] - [ sh, -xc, "echo $(date) ': hello world!'" ] - [ sh, -c, echo "=========hello world'=========" ] - ls -l /root - [ wget, "http://slashdot.org", -O, /tmp/index.html ]
“bootcmd”:
#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中的“cloud-init-per”命令示例。 从它的帮助:
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