通过 cloud-init 发出 运行 命令

Issues running commands via cloud-init

我正在从事的一个开源项目有需要 Linux 的组件,因此虚拟化通常是开发和测试新功能的最佳解决方案。我正在尝试为 Multipass 提供一个简单的 cloud-init 文件,它将通过从 Git 中提取我们的文件并自动在 VM 中设置它们来使用我们的代码配置 VM。然而,尽管启动的额外时间似乎表明进程正在 运行,但实际上似乎没有文件保存到主目录,即使对于更简单的情况,即

runcmd:
  - [ cd, ~ ]
  - [ touch test ]
  - [ echo 'test' > test ]

我只是错误地配置了 cloud-init 还是我遗漏了一些重要的东西?

这里有几个问题。

首先,您的云配置用户数据必须以以下行开头:

#cloud-config

没有那条线,cloud-init 不知道如何处理它。如果您要提交这样的 user-data 配置:

#cloud-config
runcmd:
  - [ cd, ~ ]
  - [ touch test ]
  - [ echo 'test' > test ]

您会在 /var/log/cloud-init-output.log 中发现以下错误:

runcmd.0: ['cd', None] is not valid under any of the given schemas
/var/lib/cloud/instance/scripts/runcmd: 2: cd: can't cd to None
/var/lib/cloud/instance/scripts/runcmd: 3: touch test: not found
/var/lib/cloud/instance/scripts/runcmd: 4: echo 'test' > test: not found

您将在 the documentation 中找到这些问题的解决方案,其中包括关于 runcmd 的注释:

# 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'

您传递了一个列表列表,因此行为受“*如果项目是一个列表,项目将被正确执行,就像传递给 execve(3) 一样(第一个参数作为命令) ”。在这种情况下,[cd, ~] 中的 ~ 没有任何意义——命令没有被 shell 执行,所以没有什么可以扩展 ~

后两个命令包含在单个列表项中,并且您的系统上没有名为 touch testecho 'test' > test 的命令。

这里最简单的解决方案是直接传入一个字符串列表:

#cloud-config
runcmd:
  - cd /root
  - touch test
  - echo 'test' > test

我在这里用 cd /root 替换了 cd ~,因为它似乎更明确(而且您知道这些命令无论如何都是 运行 和 root)。