Amazon ec2 如何使cloud init启动脚本在每次EC2实例启动时运行?

Amazon ec2 如何使cloud init启动脚本在每次EC2实例启动时运行?,amazon-ec2,cloud,cloud-init,Amazon Ec2,Cloud,Cloud Init,我有一个EC2实例运行一个基于AmazonLinuxAMI的AMI。与所有此类AMI一样,它支持系统根据传递到每个实例的用户数据运行启动脚本。在这种特殊情况下,我的用户数据输入恰好是一个包含文件,它源于其他几个启动脚本: #include http://s3.amazonaws.com/path/to/script/1 http://s3.amazonaws.com/path/to/script/2 第一次启动实例时,cloud init启动脚本运行正常。但是,如果我对实例进行软重启(例如,通

我有一个EC2实例运行一个基于AmazonLinuxAMI的AMI。与所有此类AMI一样,它支持系统根据传递到每个实例的用户数据运行启动脚本。在这种特殊情况下,我的用户数据输入恰好是一个包含文件,它源于其他几个启动脚本:

#include
http://s3.amazonaws.com/path/to/script/1
http://s3.amazonaws.com/path/to/script/2
第一次启动实例时,cloud init启动脚本运行正常。但是,如果我对实例进行软重启(例如,通过运行
sudo shutdown-r
),实例将在第二次运行启动脚本的情况下重新启动。如果我进入系统日志,我可以看到:

Running cloud-init user-scripts
user-scripts already ran once-per-instance
[  OK  ]
这不是我想要的——我可以看到在每个实例生命周期中只运行一次的启动脚本的实用性,但在我的情况下,这些脚本应该在每次实例启动时运行,就像正常的启动脚本一样

我意识到一个可能的解决方案是在第一次运行后手动将脚本插入
rc.local
。然而,这似乎很麻烦,因为cloudinit和rc.d环境有细微的不同,我现在必须在第一次启动和所有后续启动时分别调试脚本


有人知道我如何告诉cloud init始终运行我的脚本吗?这听起来很像cloud init的设计者们会考虑的事情。

一种可能,尽管有点黑客味,但它可以删除cloud init用来确定用户脚本是否已经运行的锁文件。在我的例子(Amazon Linux AMI)中,这个锁文件位于
/var/lib/cloud/sem/
中,名为
user scripts.i-7f3f1d11
(最后的散列部分在每次启动时都会更改)。因此,添加到Include文件末尾的以下用户数据脚本将实现此目的:

#!/bin/sh
rm /var/lib/cloud/sem/user-scripts.*

我不确定这是否会对其他任何东西产生不利影响,但它在我的实验中起到了作用。

/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


祝你好运

在11.10、12.04及更高版本中,您可以通过让“脚本用户”运行“始终”来实现这一点。 在/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_final_modules:
 - rightscale_userdata
 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - [scripts-user, always]
 - keys-to-console
 - phone-home
 - final-message
也可以像您在描述中所做的那样“包括”。 不幸的是,现在您无法修改“cloud\u final\u modules”,只能覆盖它。我希望在某个时候添加修改配置部分的功能

在云配置文档中有更多关于这方面的信息


或者,您可以将文件放入/var/lib/cloud/scripts/per boot中,它们将通过“scripts per boot”路径运行。

cloud init现在本机支持此功能,请参阅文档()中的runcmd vs bootcmd命令说明:

“runcmd”:

“bootcmd”:

还要注意bootcmd中的“cloudinitper”命令示例。从它的帮助:

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

我与这个问题斗争了将近两天,尝试了我能找到的所有解决方案,最后结合几种方法,得出以下结论:

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跨区域复制过程的设置。

请使用bash脚本上方的以下脚本

示例:我正在将hello world打印到我的文件中

在添加到userdata之前停止实例

剧本
另一种方法是在用户数据脚本中使用
#cloud boothook
。从:

云引导钩

  • 以#cloud boothook或内容类型开始:text/cloud boothook
  • 此内容是引导钩数据。它存储在/var/lib/cloud下的文件中,然后立即执行
  • 这是最早的“钩子”没有提供只运行一次的机制。引导钩必须小心 这本身就是一个问题。它在环境中提供了实例ID 变量实例\ ID。使用此变量为每个实例提供一次 引导钩数据集

“散列部分”似乎是一个amazon机器id,不是吗?它看起来像一个AWS实例id,在这种情况下,它会随着每个实例的启动而改变,但在同一实例的停止和重新启动时保持不变。>我希望在某个时候添加修改配置部分的功能。现在是否添加了此功能?我看到最新的cloud init中有一个“合并”功能,但我不知道如何使用它来更改“脚本用户”行。不管我通过了什么选项,它都会覆盖整个列表。这里有一行代码可以进行在线修改:
sed-I's/scripts user$/\[scripts user,always\]/'/etc/cloud/cloud.cfg
将文件放入
/var/lib/cloud/scripts/per boot
似乎容易多了,我可以用它来设置。从2017年开始,数据已经转移到其他地方。使用/etc/cloud/cloud.cfg.d/并在那里放置一个新文件。@Chetabahana您知道这是否仍然有效吗?即使使用了
sudo chmod a+x run.sh
sudo chown root:root run.sh
,我也无法让它工作。编辑:事实上,无论我尝试什么,它都会运行内置的东西,但不会运行我自己的可执行文件。我不得不改用crontab.update answer,其中引用了官方文档中的相应引用,并链接到原始文档仅供参考bootcmd部分在未完全启动的系统上执行,可能无法按预期工作。如何使用ec2 UserData中的cloud init per在每次启动时运行cfn init脚本?嘿!我将bash脚本文件复制到/var/lib/cloud/scripts/per instance文件夹中,但是,当我实例化一个实例时,脚本不会运行。请帮助你说你“结合了许多方法”。您能否详细说明一下,您的上述cfn中的哪些项目有助于在每次启动时运行您的userdata脚本?谢谢。@CBP,基本上,
AWS::CloudFormation::Init
wi
#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 ]
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
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}
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
--//