用户数据脚本未给出原因而失败

24

我正在使用Web控制台启动Amazon Linux实例(ami-fb8e9292),将数据粘贴到用户数据框中以在启动时运行脚本。如果我使用亚马逊提供的示例来启动Web服务器,它会起作用。但是当我运行自己的脚本(也是一个#!/bin/bash脚本)时,它没有被执行。

如果我查看var/log/cloud-init.log,它对这个问题没有任何有用的信息:

May 22 21:06:12 cloud-init[1286]: util.py[DEBUG]: Running command ['/var/lib/cloud/instance/scripts/part-001'] with allowed return codes [0] (shell=True, capture=False)
May 22 21:06:16 cloud-init[1286]: util.py[WARNING]: Failed running /var/lib/cloud/instance/scripts/part-001 [2]
May 22 21:06:16 cloud-init[1286]: util.py[DEBUG]: Failed running /var/lib/cloud/instance/scripts/part-001 [2]
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/cloudinit/util.py", line 637, in runparts
    subp([exe_path], capture=False, shell=True)
  File "/usr/lib/python2.6/site-packages/cloudinit/util.py", line 1528, in subp
    cmd=args)
ProcessExecutionError: Unexpected error while running command.
Command: ['/var/lib/cloud/instance/scripts/part-001']
Exit code: 2
Reason: -
Stdout: ''
Stderr: ''

如果我通过SSH登录到实例并使用sudo su,然后直接执行shell脚本:

/var/lib/cloud/instance/scripts/part-001

然后它就可以正常运行了。如果我模拟 cloud-init 的运行方式,它也能正常工作:

then it runs fine. Also, it works if I emulate the way cloud-init runs it:

->

然后它就可以正常运行了。如果我模拟 cloud-init 的运行方式,它也能正常工作:

python
>>> import cloudinit.util
>>> cloudinit.util.runparts("/var/lib/cloud/instance/scripts/")

如果我故意在脚本中引入错误,使用这两种方法之一,则会产生错误消息。那么我该如何调试有用的调试输出有选择性地缺失呢?


1
我也遇到了这个问题。我得到了一个退出码为1。 - Mark Kasson
我有同样的问题。你解决了吗? - Douglas Ferguson
不是的。我刚刚停止使用亚马逊Linux。我认为他们自己的定制应该是最受支持的AMI,但它似乎是最不受支持的一个。 - jjanes
6个回答

13

不要使用/var/log/cloud-init.log,而是在/var/log/cloud-init-output.log中查找关键字,如“Failed”、“ERROR”、“WARNING”或“/var/lib/cloud/instance/scripts/”,因为它包含的错误信息通常更加清晰。

例如,运行错误命令会在/var/log/cloud-init-output.log中产生以下错误:

/var/lib/cloud/instance/scripts/part-001: line 10: vncpasswd: command not found
cp: cannot stat '/lib/systemd/system/vncserver@.service': No such file or directory
sed: can't read /etc/systemd/system/vncserver@.service: No such file or directory
Failed to execute operation: No such file or directory
Failed to start vncserver@:1.service: Unit not found.
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Cleaning repos: amzn2-core amzn2extra-docker amzn2extra-epel

/var/log/cloud-init.log文件的末尾,您将收到一个简短的通用错误消息:

Aug 31 15:14:00 cloud-init[3532]: util.py[DEBUG]: Failed running /var/lib/cloud/instance/scripts/part-001 [1]
    Traceback (most recent call last):
      File "/usr/lib/python2.7/site-packages/cloudinit/util.py", line 910, in runparts
        subp(prefix + [exe_path], capture=False, shell=True)
      File "/usr/lib/python2.7/site-packages/cloudinit/util.py", line 2105, in subp
        cmd=args)
    ProcessExecutionError: Unexpected error while running command.
    Command: ['/var/lib/cloud/instance/scripts/part-001']
    Exit code: 1
    Reason: -
    Stdout: -
    Stderr: -
    cc_scripts_user.py[WARNING]: Failed to run module scripts-user (scripts in /var/lib/cloud/instance/scripts)

(*) 尝试使用 grep 仅提取相关的错误信息:
grep -C 10 '<search-keyword>' cloud-init-output.log

2
确实是这样做了,但我收到的最清晰的信息是“运行模块[...]失败”。没有原因。没有解释。什么都没有。它只是“失败”了。当这条消息被声明为警告时,情况变得更有趣,而事实上它应该是致命错误,立即终止初始化过程。 - Akito
感谢您的答复!它对我调试非常有帮助。 - Luis Felipe

8

我不确定是否对所有人都适用,但我遇到了这个问题,并通过更改第一行来解决它:

#!/bin/bash -e -v

仅需这样:

#!/bin/bash

当然,现在我的脚本失败了,我不知道它到底执行了多少,但至少我终于让它运行起来了。 :)

3
你可以使用以下命令重新添加这些内容: set -v -e # 显示详细信息并在出现错误时退出, 或者:set -x # 调试模式 - user2707671
3
我遇到了与 #!/bin/bash -xe 相同的问题。 - Ray
我的问题与自动删除有关,在修复问题之前是 yum autoremove,修复后是 yum autoremove -y。我设置了标志 set -ex 来检测是否存在问题以停止脚本,不幸的是 AWS Python 脚本没有显示良好的错误消息。 - Edenshaw

5
希望它能为某些人减少调试时间。 在我的/var/log/cloud-init-output.log中没有任何明确的错误信息,只有这样一个信息:

2021-04-07 10:36:57,748 - cc_scripts_user.py [WARNING]: 无法运行模块“scripts-user”(位于/var/lib/cloud/instance/scripts中的脚本) 2021-04-07 10:36:57,748 - util.py[WARNING]: 运行模块“scripts-user”(<module 'cloudinit.config.cc_scripts_user' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_scripts_user.py'>)失败

经过一些调查后,我意识到原因是 shebang 字符串中的拼写错误:#!?bin/bash 而不是 #!/bin/bash

4

我有一个类似的问题,但是我成功地解决了它。我发现sudo无法设置环境变量EC2_HOME。我在我的configset中做了很多使用aws cli的事情,为了让这些工作正常,需要设置EC2_HOME。所以,我去掉了我的configset和UserData中的sudo。

早先,当我遇到这个问题时,我的UserData看起来像:

"UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
                                "#!/bin/bash\n",
                                "sudo yum update -y aws-cfn-bootstrap\n",

                                "# Install the files and packages and run the commands from the metadata\n",
                                "sudo /opt/aws/bin/cfn-init -v --access-key ", { "Ref" : "IAMUserAccessKey" }, " --secret-key ", { "Ref" : "SecretAccessKey" },  
                                "         --stack ", { "Ref" : "AWS::StackName" },
                                "         --resource NAT2 ",
                                "         --configsets config ",
                                "         --region ", { "Ref" : "AWS::Region" }, "\n"
                        ]]}}

经过更改后,我的UserData看起来像这样:

"UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
                                "#!/bin/bash -xe\n",
                                "yum update -y aws-cfn-bootstrap\n",

                                "# Install the files and packages and run the commands from the metadata\n",
                                "/opt/aws/bin/cfn-init -v --access-key ", { "Ref" : "IAMUserAccessKey" }, " --secret-key ", { "Ref" : "SecretAccessKey" },  
                                "         --stack ", { "Ref" : "AWS::StackName" },
                                "         --resource NAT2 ",
                                "         --configsets config ",
                                "         --region ", { "Ref" : "AWS::Region" }, "\n"
                        ]]}}

同样地,我移除了在我的配置集中所有的sudo调用。


1

我经历过这种情况,我的情况也与#!bin/bash前面的空格有关。

我使用boto3的python代码启动了一个实例。

ec2 = boto3.resource('ec2', region_name='eu-south-1')
instance = ec2.create_instances(
    image=AMI_IMAGE_ID,
    InstanceType=INSTANCE_TYPE,
    ...
    UserData=USER_DATA_SCRIPT
    ...
)

USER_DATA_SCRIPT的定义如下:

USER_DATA_SCRIPT = """
#!/bin/bash
apt update -y
apt upgrade -y
...
"""

这段文本开头有空格,导致脚本在执行时出现错误,但未提供更多详细信息,详见/var/log/cloud-init-output.log

将其修改为:

USER_DATA_SCRIPT = """#!/bin/bash
apt update -y
apt upgrade -y
...
"""

问题已解决。


1
在我的情况下,cloudinit无法启动脚本,因为userdata必须以特定格式开头。
#!bin/bash

没有空格在前面! 这是一个很好的AWS bug,需要花费大量时间进行故障排除 :)


这是已经回答过的相同答案。考虑留下评论到原始答案中。 - Maksim Luzik
实际上是 #!/bin/bash - Luis Felipe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接