How to make Ansible execute a shell script if a pa

2019-03-08 01:38发布

How can I make Ansible execute a shell script if a (rpm) package is not installed? Is it somehow possible to leverage the yum module?

标签: ansible
7条回答
太酷不给撩
2楼-- · 2019-03-08 02:09

Since Ansible 2.5, you can use the package_facts module:

- 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'

Note: you need the python bindings for apt/rpm installed on the target, e.g. python-apt for Debian.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-03-08 02:11

I don't think the yum module would help in this case. It currently has 3 states: absent, present, and latest. Since it sounds like you don't want to actually install or remove the package (at least at this point) then you would need to do this in two manual steps. The first task would check to see if the package exists, then the second task would invoke a command based on the output of the first command.

If you use "rpm -q" to check if a package exists then the output would look like this for a package that exists:

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

and like this if the package doesn't exist:

# rpm -q httpdfoo
package httpdfoo is not installed

So your ansible tasks would look something like this:

- 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

The rpm command will also exit with a 0 if the package exists, or a 1 if the package isn't found, so another possibility is to use:

when: rpm_check.rc == 1
查看更多
放荡不羁爱自由
4楼-- · 2019-03-08 02:12

Based on the Bruce P answer above, a similar approach for apt/deb files is

- 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
查看更多
戒情不戒烟
5楼-- · 2019-03-08 02:17

Related to this.

Putting everything together, complete playbook for Debian (Ubuntu) which Updates package only if it's already installed:

---
- 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

Sadly Ansible still hasn't built-in support for making simple package updating, see ex: https://github.com/ansible/ansible/issues/10856

查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-03-08 02:18

If the package is installable through the system package manager (yum, apt, etc) itself, then you can make use of the check mode flag of ansible to register installation status without actually installing the package.

- 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 
查看更多
ゆ 、 Hurt°
7楼-- · 2019-03-08 02:21

I find using shell or command module is not "ansiblic".

I prefer to use yum module and json_query filter to check if a package is already installed. E.g. httpd package :

    - yum:
        list: httpd
      register: apache_service

    - assert:
        that:
          - "'installed' in apache_service|json_query('results[*].yumstate')"
      msg: 'httpd is not installed'
查看更多
登录 后发表回答