Ansible check if software package is installed on Linux

How can I check if a software package is installed on a Linux system using Ansible?. You can use Ansible automation tool to query installation status of a package on Linux a system. From the results a condition can then be used, e.g skip a task if package is installed, or install if check status is failed.

We’ll have two test scenarios.

  1. Check if package is installed and output status in the results message
  2. Execute another task based on the check results.

We will be checking if vim package is installed on either Debian based or Red Hat based Linux distribution.

Using Ansible command module

Create a new playbook file called check_package.yml

vim check_package.yml

Here are the contents of the file.

---
- hosts: servers
  #connection: local # When running locally
  vars:
    package_names:
      - vim
  tasks:
    - name: "Check if listed package is installed or not on Debian Linux family"
      command: dpkg-query -l "{{ item }}"
      loop: "{{ package_names }}"
      register: package_check
      when: ansible_facts['os_family'] == "Debian"

    - name: "Check if listed package is installed or not on Red Hat Linux family"
      command: rpm -q "{{ item }}"
      loop: "{{ package_names }}"
      register: package_check
      when: ansible_facts['os_family'] == "RedHat"
    - name: "Print execution results"
      debug:
        msg: "Package is installed"
      when: package_check is succeeded

Create a hosts inventory file:

$ vim hosts
[all:vars]
ansible_user='root' #change accordingly
ansible_become=yes
ansible_become_method=sudo

[servers]
10.10.10.11
10.10.10.12

Validate Playbook syntax:

$ ansible-playbook --syntax-check check_package.yml -i hosts
playbook: check_package.yml

Run the playbook:

$ ansible-playbook -i hosts check_package.yml

PLAY [servers] ***************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [server1]
ok: [server2]

TASK [Check if vim package is installed or not on Debian Linux family] *******************************************************************************************
changed: [server1] => (item=vim)
changed: [server2] => (item=vim)

TASK [Check if vim package is installed or not on Red Hat Linux family] ******************************************************************************************
skipping: [server1] => (item=vim)
skipping: [server2] => (item=vim)

TASK [Print executaion results] **********************************************************************************************************************************
ok: [server1] => {
    "msg": "Package is installed"
}
ok: [server2] => {
    "msg": "Package is installed"
}

PLAY RECAP *******************************************************************************************************************************************************
server1                    : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
server2                    : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Using Ansible package module

The same results can be achieved using package module. Below is the modified playbook using package module.

$ vim check_package1.yml
---
- hosts: servers
  #connection: local # When running locally
  vars:
    package_names:
      - vim 
      - telnet
  tasks:
    - name: "Check if listed package is installed or not on Debian Linux family"
      ansible.builtin.package:
        name: "{{ item }}"
        state: present
      check_mode: true
      loop: "{{ package_names }}"
      register: package_check

    - name: "Print execution results"
      debug:
        msg: "Package is installed"
      when: package_check is succeeded

Execution:

$ ansible-playbook -i hosts check_package1.yml

PLAY [servers] ***************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [server1]
ok: [server2]

TASK [Check if vim package is installed or not on Debian Linux family] *******************************************************************************************
ok: [server1] => (item=vim)
ok: [server1] => (item=telnet)
changed: [server2] => (item=vim)
changed: [server2] => (item=telnet)

TASK [Print execution results] ***********************************************************************************************************************************
ok: [server1] => {
    "msg": "Package is installed"
}
ok: [server2] => {
    "msg": "Package is installed"
}

PLAY RECAP *******************************************************************************************************************************************************
server1                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
server2                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Run a task based on results outcome

Let’s modify the playbook to check if packages are present locally in the system, if not install them.

$ vim check_package.yml
---
- hosts: servers
  #connection: local # When running locally
  remote_user: root
  vars:
    package_names:
      - nano
      - vim
  tasks:
    - name: "Check if listed package is installed or not on Debian Linux family"
      command: dpkg-query -l "{{ item }}"
      loop: "{{ package_names }}"
      register: debian_package_check
      when: ansible_facts['os_family'] == "Debian"

    - name: "Check if listed package is installed or not on Red Hat Linux family"
      command: rpm -q "{{ item }}"
      loop: "{{ package_names }}"
      register: redhat_package_check
      changed_when: false
      ignore_errors: true
      when: ansible_facts['os_family'] == "RedHat"

    - name: Install package if not present Debian
      ansible.builtin.package:
        name: "{{ item }}"
        state: present
      loop: "{{ package_names }}"
      when: debian_package_check is failed and ansible_facts['os_family'] == "Debian"
    
    - name: Install package if not present RedHat
      ansible.builtin.package:
        name: "{{ item }}"
        state: present
      loop: "{{ package_names }}"
      when: redhat_package_check is failed and ansible_facts['os_family'] == "RedHat"

Sample execution:

$ ansible-playbook -i hosts check_package.yml
PLAY [servers] ***************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [server1]
ok: [server2]

TASK [Check if vim package is installed or not on Debian Linux family] *******************************************************************************************
skipping: [server2] => (item=nano)
changed: [server1] => (item=nano)

TASK [Check if vim package is installed or not on Red Hat Linux family] ******************************************************************************************
skipping: [server1] => (item=nano)
failed: [server2] (item=nano) => {"ansible_loop_var": "item", "changed": false, "cmd": ["rpm", "-q", "nano"], "delta": "0:00:00.014446", "end": "2021-03-25 23:06:14.220052", "item": "nano", "msg": "non-zero return code", "rc": 1, "start": "2021-03-25 23:06:14.205606", "stderr": "", "stderr_lines": [], "stdout": "package nano is not installed", "stdout_lines": ["package nano is not installed"]}
...ignoring

TASK [Install package if not present Debian] *********************************************************************************************************************
skipping: [server1] => (item=nano)
skipping: [server2] => (item=nano)

TASK [Install package if not present RedHat] *********************************************************************************************************************
skipping: [server1] => (item=nano)
changed: [server2] => (item=nano)

PLAY RECAP *******************************************************************************************************************************************************
server1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0
server2                    : ok=3    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=1

The Playbook could need improvement to work on all Linux distributions. We just demonstrated how package checking if installed on Red Hat and Debian based system can be done.

More guides on Ansible:

Your IT Journey Starts Here!

Ready to level up your IT skills? Our new eLearning platform is coming soon to help you master the latest technologies.

Be the first to know when we launch! Join our waitlist now.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

AlmaLinux OS is a Linux operating systemd forked from RHEL by the team behind CloudLinux. It is meant to be […]

I recently experienced the error Failed creating Qemu driver: exec: “qemu-system-x86_64”: executable file not found in $PATH while trying to […]

In a Linux file system, files are stored within a single directory structure, called a virtual directory. The virtual directory […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.