2014-02-19 108 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' 
相關問題