【问题标题】:How to prevent conditioned command evaluation in Ansible's shell provisioning?如何防止 Ansible 的 shell 配置中的条件命令评估?
【发布时间】:2019-10-09 10:04:50
【问题描述】:

我有以下多机 Vagrant 设置:

Vagrant.configure(2) do |config|

  config.vm.define "xfcevm" do |xfcevm|
    xfcevm.vm.box = "generic/ubuntu1904"
    xfcevm.vm.hostname = "xfcevm"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "ubuntu-xfce"
    end
  end

  config.vm.define "kdevm" do |kdevm|
    kdevm.vm.box = "generic/arch"
    kdevm.vm.hostname = "kdevm"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "arch-kde"
    end
  end

  ## only Arch doesn't ship with Python installed
  config.vm.provision "shell", inline: "which python || sudo pacman --noconfirm -S python"

  config.vm.provider "virtualbox" do |vb|
    vb.gui = true
    vb.memory = "2048"
    vb.cpus = 1
    vb.customize ["modifyvm", :id, "--vram", "32"]
  end

  config.vm.provision "ansible" do |ansible|
    ansible.verbose = "v"
    ansible.compatibility_mode = "2.0"
    ansible.playbook = "setup.yml"
    ansible.inventory_path = "hosts"
  end

end

由于 Arch vagrant box 不包含 Python,所以我创建了一个内联 shell 提供命令,该命令应该测试 Python 的存在(which python),如果评估结果为 false,那么 pacman 安装Python 应该紧随其后。对于回显输出,不应评估第二部分,在终端中运行命令就是这种情况。

但是无论 Python 是否存在,shell 配置器都会评估 || 之后的部分。对于 Ubuntu,它会引发一个明显的错误:pacman 未安装:

$ vagrant up --provision
Bringing machine 'xfcevm' up with 'virtualbox' provider...
Bringing machine 'kdevm' up with 'virtualbox' provider...
==> xfcevm: Checking if box 'generic/ubuntu1904' version '1.9.34' is up to date...
==> xfcevm: Running provisioner: shell...
    xfcevm: Running: inline script
    xfcevm: sudo
    xfcevm: : 
    xfcevm: pacman: command not found
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.

用一个简单的 if 语句代替 || 也是如此:

config.vm.provision "shell", inline: "if [ ! `which python` ]; then sudo pacman --noconfirm -S python; fi"

【问题讨论】:

  • 我无法重现您的问题。此外,我在您的输出中没有看到which 为您的工具找到的路径。所以我强烈怀疑,根据您连接的用户,which 没有找到您的 python 安装,导致您的第二个命令运行。
  • 我已经弄清楚并提供了答案。等待您的时间!

标签: python ruby ansible vagrant virtualbox


【解决方案1】:

实际的问题是两件事的结合:在 Arch 中使用 python 作为 Python3 的别名(与 Ubuntu 中 python 是 Python2 的别名相反)和 Ubuntu 不附带 Python2 的事实(我们不'Ansible 不需要它,我们使用 Python3)。

所以解决方案是同时检查pythonpython3

config.vm.provision "shell", inline: "if [ ! `which python`] && [ ! `which python3` ]; then sudo pacman --noconfirm -S python; fi"

【讨论】:

    【解决方案2】:

    在我的机器上使用以下 Vagranfile 进行测试后:

     Vagrant.configure(2) do |config|
         config.vm.box = "generic/ubuntu1904"
         config.vm.hostname = "test"
         config.vm.network "private_network", type: "dhcp"
         config.vm.synced_folder ".", "/vagrant", disabled: true
         config.vm.provider "virtualbox" do |v|
             v.memory = 2048
             v.cpus = 2
         end
         config.vm.provision "default", type: "shell", inline: "which python", run: "always"
     end
    

    这是vagrant up 的结果(仅最后几行)

    ==> default: Running provisioner: default (shell)...
        default: Running: inline script
    The SSH command responded with a non-zero exit status. Vagrant
    assumes that this means the command failed. The output for this command
    should be in the log above. Please read the output to determine what
    went wrong.
    

    交互式检查:

    $ vagrant ssh
    Last login: Wed Oct  9 15:33:22 2019 from 10.0.2.2
    vagrant@test:~$ which python
    vagrant@test:~$ echo $?
    1
    vagrant@test:~$ which python3
    /usr/bin/python3
    vagrant@test:~$ echo $?
    0
    vagrant@test:~$
    

    结论:你得到的是完全连贯的。 python 不存在于您的 ubuntu 映像中,因此您的命令的其余部分将运行。您的方案有缺陷,您需要找到其他方法。

    在您的上下文中,我会尝试在 ansible 中运行所有内容。这里只是一个例子,我没有测试,肯定可以大大改进

    - name: Make sure machine can run ansible
      hosts: all
      gather_facts: false
    
      tasks:
        - block:
            - name: Try to ansible-ping the host. Consider python is not installed otherwise
              ping:
    
          rescue:
            - name: No python available, install with low-level and dirty command
              become: true
              become_method: sudo
              raw: pacman --noconfirm -S python
    
    
    

    【讨论】:

    • 感谢您的宝贵时间,在看到您的答案之前,我已经提供了答案。是的,问题在于 Ubuntu 和 Arch 不同的python 别名含义。我用双|| 解决了这个问题。不知道 ansible 解决方案版本,也许如果将来当前的解决方案不再适合。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多