背景:在Puppet中可以执行一个命令, 除非它已经被执行:
exec { '/bin/echo root >> /usr/lib/cron/cron.allow': path => '/usr/bin:/usr/sbin:/bin', unless => 'grep root /usr/lib/cron/cron.allow 2>/dev/null', }
目标:执行一个命令,除非已经在Ansible中运行
方法
任务/ main.yml
- name: add vhost sensu command: rabbitmqctl add_vhost /sensu
结果
TASK [ansible-rabbitmq : add vhost sensu] ************************************** fatal: [111.222.333.444]: FAILED! => {"changed": true, "cmd": ["rabbitmqctl", "add_vhost", "/sensu"], "delta": "0:00:00.210140", "end": "2016-07-29 12:55:19.384455", "failed": true, "rc": 2, "start": "2016-07-29 12:55:19.174315", "stderr": "Error: vhost_already_exists: /sensu", "stdout": "Creating vhost \"/sensu\" ...", "stdout_lines": ["Creating vhost \"/sensu\" ..."], "warnings": []}
讨论
谷歌search, unless ansible显示此文件关于when 。 根据该文件,增加了一个when声明:
- name: add vhost sensu command: rabbitmqctl add_vhost /sensu when: rabbitmqctl list_vhosts | grep sensu
运行代码导致:
fatal: [192.168.0.9]: FAILED! => {"failed": true, "msg": "The conditional check 'rabbitmqctl list_vhosts | grep sensu' failed. The error was: template error while templating string: expected token 'end of statement block', got 'list_vhosts'. String: {% if rabbitmqctl list_vhosts | grep sensu %} True {% else %} False {% endif %}\n\nThe error appears to have been in '/etc/ansible /roles/ansible-rabbitmq/tasks/main.yml': line 10, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: add vhost sensu\n ^ here\n"}
when成功的话命令就不会运行,然后看起来更像是在Puppet中onlyif 。 register 。 如果这个文件丢失了,或者这个虚拟主机已经被一个人删除了,该怎么办? 傀儡的unless总是执行命令,以便清楚该命令是否需要执行。 我认为你要做的是这样的:
- name: get vhosts command: rabbitmqctl list_vhosts register: vhosts changed_when: false - name: add vhost sensu command: rabbitmqctl add_vhost /sensu when: "'/sensu' not in vhosts.stdout"
Re:#3 register不会创build文件。 如果通过register捕获rabbitmqctl list_vhosts的输出,则内容将与系统当前状态一样有效。
问题是when: rabbitmqctl list_vhosts | grep sensu when: rabbitmqctl list_vhosts | grep sensu 。 这里不可能使用bash。
你需要把rabbitmqctl list_vhosts | grep sensu rabbitmqctl list_vhosts | grep sensu在一个单独的任务,并注册结果在when子句中使用它。 unless类似的行为, unless你可以使用not过滤。
像这样的东西应该工作:
- name: Get rabbitmq vhosts. command: rabbitmqctl list_vhosts | grep sensu register: rabbitmq_vhosts - name: add vhost sensu command: rabbitmqctl add_vhost /sensu when: not 'sensu' in rabbitmq_vhosts.stdout
Get rabbitmq vhosts. 在这个例子中将始终执行。 仅当stringsensu不在注册的rabbitmq_vhosts时才add vhost sensu 。
有关更多信息,请参阅有关条件和jinjafilter的文档。
when选项是Ansible关于条件的唯一的东西。 但是你不能直接在那里定义一个命令。 when期望一个Jinjaexpression式,并且在Ansible控制主机上进行评估。 所以你首先需要运行一个任务来获取结果并注册。
- shell: rabbitmqctl list_vhosts | grep sensu register: sensu_vhosts - name: add vhost sensu command: rabbitmqctl add_vhost /sensu when: sensu_vhosts.stdout_lines < 1
stdout_lines是shell任务返回的所有行的数组。 所以你可以计算条目的数量,只有当返回0个项目时才运行你的任务