如果未安装包,如何使Ansible执行shell脚本

时间:2014-02-19 21:16:59

标签: ansible

如果没有安装(rpm)软件包,如何让Ansible执行shell脚本?是否有可能利用yum模块?

7 个答案:

答案 0 :(得分:65)

我不认为yum模块在这种情况下会有所帮助。它目前有3个州:缺席,现在和最新。由于听起来您不想实际安装或删除软件包(至少在此时),因此您需要在两个手动步骤中执行此操作。第一个任务将检查包是否存在,然后第二个任务将根据第一个命令的输出调用命令。

如果使用“rpm -q”来检查包是否存在,那么对于存在的包,输出将如下所示:

# rpm -q httpd
httpd-2.2.15-15.el6.centos.1.x86_64

并且如果包不存在则像这样:

# rpm -q httpdfoo
package httpdfoo is not installed

所以你的ansible任务看起来像这样:

- name: Check if foo.rpm is installed
  command: rpm -q foo.rpm
  register: rpm_check

- name: Execute script if foo.rpm is not installed
  command: somescript
  when: rpm_check.stdout.find('is not installed') != -1

如果包存在,rpm命令也会以0退出,如果找不到包,则退出1,所以另一种可能是使用:

when: rpm_check.rc == 1

答案 1 :(得分:28)

基于上面的Bruce P答案,apt / deb文件的类似方法是

- name: Check if foo is installed
  command: dpkg-query -l foo
  register: deb_check

- name: Execute script if foo is not installed
  command: somescript
  when: deb_check.stdout.find('no packages found') != -1

答案 2 :(得分:23)

与此相关。

将所有内容放在一起,完成Debian(Ubuntu)的剧本,只有在已经安装的情况下更新包:

---
- name: Update package only if already installed (Debian)
  hosts: all
  sudo: yes
  tasks:
    - name: Check if Package is installed
      shell: dpkg-query -W -f='${Status}' {{ package }} | grep 'install ok installed'
      register: is_installed
      failed_when: no
      changed_when: no

    - name: Update Package only if installed
      apt:
        name: {{ package }}
        state: latest
        update_cache: yes
      when: is_installed.rc == 0

可悲的是,Ansible仍然没有内置支持进行简单的软件包更新,请参阅例:https://github.com/ansible/ansible/issues/10856

答案 3 :(得分:19)

如果软件包可以通过系统软件包管理器(yum,apt等)本身安装,那么你可以使用ansible的检查模式标志来注册安装状态,而无需实际安装软件包。

- name: check if package is installed
  package:
    name: mypackage
    state: present
  check_mode: true
  register: mypackage_check

- name: run script if package installed
  shell: myscript.sh
  when: not mypackage_check.changed 

答案 4 :(得分:9)

您不应该使用dpkg -l package,因为它不知道您的包裹是否已被移除或仍然安装。
相反,使用dpkg -s package可能更好。

检查包装是否已安装:
- shell: dpkg -s package | grep 'install ok installed'
或者如果您不介意保留包裹或其他状态:
- shell: dpkg -s package | grep 'installed'
安装时返回0,否则返回1.

(因为我们使用管道|

,所以使用shell非常重要

答案 5 :(得分:9)

从Ansible 2.5开始,您可以使用package_facts模块:

- name: Gather package facts
  package_facts:
    manager: auto

- name: Debug if package is present
  debug:
    msg: 'yes, mypackage is present'
  when: '"mypackage" in ansible_facts.packages'

- name: Debug if package is absent
  debug:
    msg: 'no, mypackage is absent'
  when: '"mypackage" not in ansible_facts.packages'

注意:您需要在目标上安装apt / rpm的python绑定,例如python-apt代表Debian。

答案 6 :(得分:1)

我发现使用shell或命令模块不是“ansiblic”。

我更喜欢使用yum模块和json_query过滤器来检查是否已安装软件包。例如。 httpd包:

    - yum:
        list: httpd
      register: apache_service

    - assert:
        that:
          - "'installed' in apache_service|json_query('results[*].yumstate')"
      msg: 'httpd is not installed'