Aller au contenu
Infrastructure as Code medium

Module service_facts Ansible : auditer l'état des services systemd

6 min de lecture

Logo Ansible

ansible.builtin.service_facts: collecte l’état de tous les services systemd d’un managed node — running/stopped, enabled/disabled, masked. C’est l’outil pour conditionner une tâche ou auditer un parc sans parser à la main systemctl list-units.

Le résultat atterrit dans ansible_facts.services sous forme de dict — directement utilisable dans when: ou un template Jinja.

  • Collecter l’état de tous les services en une tâche.
  • Conditionner un started: ou enabled: selon l’état actuel.
  • Auditer un parc (services attendus, services en trop).
  • Éviter les redémarrages inutiles sur des plays massifs.
  • Pas besoin de become: (lecture seule).
  • Fonctionne sur systemd, upstart, sysv, AIX SRC, OpenWrt.
- name: Collecter les services
ansible.builtin.service_facts:
- name: Etat de nginx
ansible.builtin.debug:
msg: "{{ ansible_facts.services['nginx.service'].state }}"

Structure du dict retourné :

ansible_facts:
services:
nginx.service:
state: running
status: enabled
source: systemd

state = running, stopped, unknown. status = enabled, disabled, static, masked.

Démarrer un service uniquement s’il est arrêté

Section intitulée « Démarrer un service uniquement s’il est arrêté »
- name: Collecter les services
ansible.builtin.service_facts:
- name: Demarrer nginx si arrete
ansible.builtin.systemd_service:
name: nginx.service
state: started
when: ansible_facts.services['nginx.service'].state != 'running'

Avantage idempotent : sans service_facts, systemd_service: state: started reste idempotent au niveau API, mais Ansible affiche ok même quand le service n’est pas vraiment vérifié. Ici, vous lisez d’abord l’état et n’agissez que si nécessaire — utile pour des rapports ou des handlers conditionnels.

- name: Collecter les services
ansible.builtin.service_facts:
- name: Activer chronyd au boot
ansible.builtin.systemd_service:
name: chronyd.service
enabled: true
when: ansible_facts.services['chronyd.service'].status != 'enabled'

status: distingue enabled (démarrage auto), disabled, static (pas d’unit [Install], démarré seulement si dépendance), masked (interdit de démarrer).

Pattern fréquent : vérifier que tous les services attendus sont installés sur un parc.

- name: Collecter les services
ansible.builtin.service_facts:
- name: Verifier que firewalld est installe
ansible.builtin.assert:
that:
- "'firewalld.service' in ansible_facts.services"
fail_msg: "firewalld absent — installer le paquet"

'firewalld.service' in ansible_facts.services teste juste la présence du dict, pas l’état. Service installé même si désactivé → la clé existe.

Détecter les services masked (potentiellement dangereux)

Section intitulée « Détecter les services masked (potentiellement dangereux) »
- name: Collecter les services
ansible.builtin.service_facts:
- name: Lister les services masked
ansible.builtin.debug:
msg: "{{ item.key }}"
loop: "{{ ansible_facts.services | dict2items }}"
when: item.value.status == 'masked'

Un service masked ne peut pas être démarré — utile pour valider qu’un service n’a pas été désactivé en urgence par un opérateur et oublié.

SymptômeCauseFix
KeyError: 'nginx.service'Service pas installé, accès directTester d’abord 'nginx.service' in ansible_facts.services
Service présent mais state: unknownService non systemd, ou lecture incomplèteVérifier via systemctl status à la main
Lent sur grandes machines (> 200 services)Pas de cacheLancer une fois en début de play, réutiliser ensuite
status absent dans certains résultatsBackend non systemd (sysv)Tester .state plutôt que .status
  • service_facts: = lecture pure, pas d’écriture, pas de state:.
  • Résultat dans ansible_facts.services — dict indexé par nom complet (nginx.service).
  • state : running/stopped, status : enabled/disabled/static/masked.
  • Combiner avec assert pour auditer la conformité d’un parc.
  • Lancer une seule fois en début de play — les facts persistent.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn