Packer 无法以 sudo 身份执行 shell provisioner

Packer can't execute shell provisioner as sudo

我有一个 shell provisioner in packer 连接到用户 vagrant

的盒子
{
  "environment_vars": [
    "HOME_DIR=/home/vagrant"
  ],
  "expect_disconnect": true,
  "scripts": [
    "scripts/foo.sh"
  ],
  "type": "shell"
}

其中脚本内容为:

whoami
sudo su
whoami

奇怪的是输出仍然是:

==> virtualbox-ovf: Provisioning with shell script: scripts/configureProxies.sh
    virtualbox-ovf: vagrant
    virtualbox-ovf: vagrant

为什么我不能切换到root用户? 如何以 root 身份执行语句? 请注意,我不想引用 sudo "statement |foo" 之类的所有语句,而是像 sudo su

演示的那样全局切换用户

一个可能的答案似乎是: https://unix.stackexchange.com/questions/70859/why-doesnt-sudo-su-in-a-shell-script-run-the-rest-of-the-script-as-root

sudo su <<HERE
ls /root
whoami
HERE

也许有更好的答案?

您应该覆盖 execute_command。示例:

  "provisioners": [
    {
      "execute_command": "echo 'vagrant' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'",
      "scripts": [
        "scripts/foo.sh"
      ],
      "type": "shell"
    }
  ],

假设您使用的 shell provisioner 是一个 bash 脚本,您可以将我的技术添加到您的脚本中。

function if_not_root_rerun_as_root(){
    install_self
    if [[ "$(id -u)" -ne 0 ]]; then
        run_as_root_keeping_exports "[=10=]" "$@"
        exit $?
    fi
}

function run_as_root_keeping_exports(){
    eval sudo $(for x in $_EXPORTS; do printf '%s=%q ' "$x" "${!x}"; done;) "$@"
}

export EXPORTS="PACKER_BUILDER_TYPE PACKER_BUILD_NAME"
if_not_root_rerun_as_root "$@"

"$@" here on Whosebug 有很好的解释。

还有另一种解决方案,可以更简单地一起使用 2 个配置器。

Packer 的 shell 供应商可以 运行 bashsudo 权限。首先,您需要使用 file provisioner 将脚本文件从本地机器复制到远程,然后使用 shell provisioner 运行 复制它。

packer.json

{
    "vars": [...],
    "builders": [
        {
            # ...
            "ssh_username": "<some_user_other_than_root_with_passwordless_sudo>",
        }
    ],
    "provisioners": [
        {
            "type": "file",
            "source": "scripts/foo.sh",
            "destination": "~/shell.tmp.sh"
        },
        {
            "type": "shell",
            "inline": ["sudo bash ~/shell.tmp.sh"]
        }
    ]
}

foo.sh

# ...
whoami
sudo su root
whoami
# ...

output

<some_user_other_than_root_with_passwordless_sudo>
root

provisioner 完成任务后,您可以使用 shell provisioner 删除文件。

packer.json 已更新

        {
            "type": "shell",
            "inline": ["sudo bash ~/shell.tmp.sh", "rm ~/shell.tmp.sh"]
        }