从 CloudFormation::Init 命令重新启动

Rebooting From CloudFormation::Init Command

我无法通过 cfn-init 命令重启我的 EC2 实例。我的实例的 CloudFormation::Init 元数据中有以下配置键。

dns-hostname:
  commands:
    dns-hostname:
      env: { publicDns: !Ref PublicDns }
      command: |
        old=$(hostname)
        sed "s|HOSTNAME=localhost.localdomain|HOSTNAME=$publicDns|" --in-place /etc/sysconfig/network
        echo HOSTNAME changed from \"$old\" to \"$publicDns\"
        reboot
      ignoreErrors: true

该命令应该做的就是将实例的主机名更改为提供的 public DNS 名称。此更改需要重新启动才能生效,并且由于 cfn-init 不知道这一点,因此我必须在最后一行包含对 reboot 的实际调用。不幸的是,构建失败并显示以下日志消息(来自 /var/log/cfn-init.log):

2017-04-16 12:16:00,301 [DEBUG] Running command dns-hostname
2017-04-16 12:16:00,301 [DEBUG] Running test for command dns-hostname
2017-04-16 12:16:00,309 [DEBUG] Test command output: HOSTNAME will be changed to "bastion.example.com"
2017-04-16 12:16:00,309 [DEBUG] Test for command dns-hostname passed
2017-04-16 12:16:00,321 [ERROR] Command dns-hostname (old=$(hostname)
sed "s|HOSTNAME=localhost.localdomain|HOSTNAME=$publicDns|" --in-place /etc/sysconfig/network
echo HOSTNAME changed from \"$old\" to \"$publicDns\"
reboot
) failed
2017-04-16 12:16:00,321 [DEBUG] Command dns-hostname output: HOSTNAME changed from "ip-10-0-128-4" to "bastion.example.com"
/bin/sh: line 3: reboot: command not found
2017-04-16 12:16:00,321 [INFO] ignoreErrors set to true, continuing build

显然,实际的主机名更改并没有失败,只是对 reboot 的调用。如果我尝试使用 shutdown -r 而不是 reboot,我会收到相同的错误消息,如果我尝试使用绝对路径 (sbin/reboot),则它会挂起并且堆栈创建超时.这些非常基本的命令怎么找不到?我在这里错过了一些简单的东西吗?感谢您的帮助!

编辑:据this post, when common commands are not available, it may be due to a screwed up PATH. And indeed, the CloudFormation::Init docs说使用env 属性会覆盖当前环境,可能包括PATH.但是,我在命令中的 echo $PATH 模板中添加了一行,结果是:“usr/local/bin:/bin:/usr/bin”。所以我的 PATH 仍然包含 bash 可执行文件的路径,我仍然很困惑...

好吧,看起来 env 属性 问题。尽管我认为我的 PATH 仍然有必要的路径来找到 bash 可执行文件并因此 运行 reboot 命令,但直到我删除了 env 属性 从我的模板中,一切都能够成功构建。我在使 reboot 命令按预期运行时仍然遇到了一些麻烦,因为该命令似乎并没有在您调用它时立即 运行。例如,下面的代码将输出数字 1-10 before rebooting.

echo 1
echo 2
echo 3
echo 4
echo 5
reboot
echo 6
echo 7
echo 8
echo 9
echo 10

因此,实例显然会尝试在 运行ning 其他来自稍后 CloudFormation::Init 配置的命令的过程中重新启动,从而导致 cfn-init 失败。我对此的解决方案只是 运行 配置 commands 块,在所有其他配置之后手动调用 reboot。长话短说,这是工作模板片段:

other-config:
  ...

# This config comes after the other b/c it manually calls 'reboot'
dns-hostname:
  commands:
    dns-hostname:
      command: !Sub |
        publicDns=${PublicDns}
        old=$(hostname)
        sed "s|HOSTNAME=localhost.localdomain|HOSTNAME=$publicDns|" --in-place /etc/sysconfig/network
        echo HOSTNAME changed from \"$old\" to \"$publicDns\"
        reboot
      ignoreErrors: true
# Any other configs that call reboot can follow