我如何在每次EC2实例启动时运行cloud-init启动脚本?

| 我有一个运行基于Amazon Linux AMI的AMI的EC2实例。与所有此类AMI一样,它支持cloud-init系统,用于基于传递到每个实例中的用户数据来运行启动脚本。在这种情况下,我的用户数据输入恰好是包含其他几个启动脚本的包含文件:
#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的设计师会考虑的事情。     
已邀请:
        在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
就像您在说明中所做的那样,也可以将其“ #included”。 不幸的是,现在您不能修改\'cloud_final_modules \',而只能对其进行覆盖。我希望可以在某个时候添加修改配置节的功能。 在以下位置的cloud-config文档中有关于此的更多信息 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 \'路径运行。     
        在
/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现在原生支持此功能,请参阅文档(http://cloudinit.readthedocs.io/zh-CN/latest/topics/examples.html#run-commands-on-first-boot)中的runcmd vs bootcmd命令描述: \“ 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
    
        一种可能性(尽管有些骇人听闻)是删除cloud-init用于确定用户脚本是否已经运行的锁定文件。在我的情况下(Amazon Linux AMI),此锁定文件位于
/var/lib/cloud/sem/
中,并命名为
user-scripts.i-7f3f1d11
(末尾的哈希部分在每次引导时都会更改)。因此,将以下用户数据脚本添加到Include文件的末尾即可解决问题:
#!/bin/sh
rm /var/lib/cloud/sem/user-scripts.*
我不确定这是否会对其他任何事情产生不利影响,但是在我的实验中确实有效。     
        请在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
--//
    
        我在这个问题上苦苦挣扎了近两天,尝试了所有可以找到的解决方案,最后,结合了几种方法,得出了以下结论:
MyResource:
  Type: AWS::EC2::Instance
  Metadata:
    AWS::CloudFormation::Init:
      configSets:
        setup_process:
          - \"prepare\"
          - \"run_for_instance\"
      prepare:
        commands:
          01_apt_update:
            command: \"apt-get update\"
          02_clone_project:
            command: \"mkdir -p /replication && rm -rf /replication/* && git clone https://github.com/awslabs/dynamodb-cross-region-library.git /replication/dynamodb-cross-region-library/\"
          03_build_project:
            command: \"mvn install -DskipTests=true\"
            cwd: \"/replication/dynamodb-cross-region-library\"
          04_prepare_for_apac:
            command: \"mkdir -p /replication/replication-west && rm -rf /replication/replication-west/* && cp /replication/dynamodb-cross-region-library/target/dynamodb-cross-region-replication-1.2.1.jar /replication/replication-west/replication-runner.jar\"
      run_for_instance:
        commands:
          01_run:
            command: !Sub \"java -jar replication-runner.jar --sourceRegion us-east-1 --sourceTable ${TableName} --destinationRegion ap-southeast-1 --destinationTable ${TableName} --taskName -us-ap >/dev/null 2>&1 &\"
            cwd: \"/replication/replication-west\"
  Properties:
    UserData:
      Fn::Base64:
        !Sub |
          #cloud-config
          cloud_final_modules:
           - [scripts-user, always]
          runcmd:
           - /usr/local/bin/cfn-init -v -c setup_process --stack ${AWS::StackName} --resource MyResource --region ${AWS::Region}
           - /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyResource --region ${AWS::Region}
这是DynamoDb跨区域复制过程的设置。     
        另一种方法是在用户数据脚本中使用“ 17”。从文档:   云展位         以#cloud-boothook或Content-Type:text / cloud-boothook开头。   该内容是展位数据。它存储在/ var / lib / cloud下的文件中,然后立即执行。   这是最早的“挂钩”。没有提供仅运行一次的机制。展位必须保重   这本身。在环境中提供了实例ID   变量INSTANCE_ID。使用此变量提供一次实例   布告集数据集。        

要回复问题请先登录注册