2014-02-19 73 views

回答

54

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

如果用“转-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 
+8

该命令的问题是,如果'rpm -q'退出0(没有找到包),该剧本将失败。为了防止在任务中附加:'ignore_errors:True',以便在后续任务中使用输出来安装rpm。 – romanofski

+3

此外,您可能想要添加'changed_when:no'来强制命令模块不要说某些事情已经改变。 – Alicia

+3

另外,为避免找不到软件包时的失败消息,您可以设置'failed_when:rpm_check.rc> 1'。 – Alicia

25

基于上述布鲁斯P答复,对易于/ 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 
+1

我需要添加'failed_when:False' –

+1

我想指出的是,从Ansible 2.1开始,apt模块有一个名为'only_upgrade'的选项,该选项专为此目的而设计。文档描述了交换机:'只有安装/升级软件包,如果它已经安装。' – Erathiel

+2

@Erathiel我认为如果找到给定的包,这个剧本可以解决的问题是运行一个“确定的”任务。所以不一定要安装一个丢失的软件包,它可能是别的。 'only_upgrade'选项用于确保软件包的安装或更新非常类似于'state'所发生的情况。 – JohnnyQ

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

+1

正如[注意下文](https://stackoverflow.com/a/36405647/2192488)所示,使用'shell:dpkg --status {{package}} | grep'install ok installed''比使用'command :dpkg-query -l {{package}}'。 –

8

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

要检查是否安装了软件包:
- shell: dpkg -s package | grep 'install ok installed'
或者,如果你不介意搁置或其他国家的包装:
- shell: dpkg -s package | grep 'installed'
这回安装时0和1,如果不是。

(使用shell是很重要的,因为我们使用的是管道|

7

如果包是通过系统的包管理器安装(YUM,APT等)本身,那么你可以使用支票模式标志可以注册安装状态而无需实际安装软件包。

- 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

通过使用'package'模块而不是特定的'yum',这将使它成为最好的答案,因为它将在RHEL或Debian系列的Linux发行版上工作。做得好! – Huygens

+1

调整后,感谢您的反馈@Huygens – reegnz

+0

这对我没有用。如果未安装该软件包,Ansible会出错。我必须在“检查软件包是否安装”部分添加“ignore_errors:yes”。 –

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' 
相关问题