如何在Ansible的shell配置中防止条件命令求值?

2024-05-23 18:09:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下多机流浪设置:

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 provision命令,该命令应该测试Python的存在性(通过which python),如果该命令的计算结果为false,那么就应该安装Python。对于回音输出,第二部分不应该被计算,这是在终端中运行命令的情况。你知道吗

但是shell provisioner不管Python是否存在,都会对||之后的部分进行求值。对于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"

Tags: boxconfigwithvmansiblepacmanshellprovider
2条回答

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

 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


实际问题是两个方面的结合:在Arch中使用Python3的别名Python3(与Ubuntu中Python2的别名Python3相反),以及Ubuntu没有附带Python2(我们不需要它,我们使用Python3)。你知道吗

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

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

相关问题 更多 >