5.3 : lineinfile vs template : quand utiliser quoi

On vient de voir template en détail : idéal pour générer un fichier complet à partir d’un gabarit. Mais parfois, le besoin est bien plus modeste : modifier une seule ligne dans un fichier existant, sans toucher au reste. Utiliser template pour ça serait disproportionné — c’est là qu’intervient lineinfile.

Le cas d’usage de lineinfile

Imaginons qu’on doive simplement s’assurer qu’une ligne précise est présente dans un fichier de configuration système, sans réécrire le fichier entier :

- name: S'assurer que le swappiness est réglé correctement
  ansible.builtin.lineinfile:
    path: /etc/sysctl.conf
    line: "vm.swappiness=10"
    regexp: "^vm.swappiness="

Ici, regexp indique à Ansible quelle ligne chercher pour la remplacer si elle existe déjà (peu importe sa valeur actuelle), et line indique la ligne finale voulue. Si aucune ligne ne correspond au regexp, la ligne est simplement ajoutée à la fin du fichier.

Pourquoi ne pas utiliser template pour ce cas ?

Techniquement, on pourrait générer tout /etc/sysctl.conf avec un template. Mais ce fichier appartient au système, contient potentiellement des dizaines de réglages ajoutés par d’autres processus, d’autres paquets, ou d’autres administrateurs. Le réécrire entièrement avec template écraserait tout ce qui n’est pas dans votre gabarit — un risque bien réel de casser des réglages qui n’ont rien à voir avec votre playbook.

lineinfile respecte le reste du fichier : il ne touche qu’à la ligne qui l’intéresse, laisse tout le reste intact.

Le tableau de décision

SituationModule à privilégier
Générer un fichier de configuration entier, propre à votre applicationtemplate
Modifier une seule ligne dans un fichier système partagélineinfile
Ajouter un bloc de plusieurs lignes identifiable (voir ci-dessous)blockinfile
Le fichier n’est géré par personne d’autre que votre playbooktemplate (plus lisible et maintenable qu’une série de lineinfile)

Le cas intermédiaire : blockinfile

Entre « une seule ligne » et « tout le fichier », il existe un module qu’on n’a pas encore cité : blockinfile. Il insère (ou retire) un bloc entier, délimité par des marqueurs automatiques, sans toucher au reste du fichier :

- name: Ajouter un bloc de configuration personnalisé
  ansible.builtin.blockinfile:
    path: /etc/hosts
    block: |
      10.0.1.10 nrd-web1
      10.0.1.20 nrd-db1

Ansible entoure automatiquement ce bloc de commentaires marqueurs (# BEGIN ANSIBLE MANAGED BLOCK / # END ANSIBLE MANAGED BLOCK), ce qui lui permet de retrouver exactement ce bloc lors d’une prochaine exécution, pour le mettre à jour ou le supprimer proprement — sans jamais toucher au reste du fichier.

regexp : le piège à connaître avec lineinfile

Un point d’attention important : sans regexp (ou avec un regexp trop large), lineinfile peut ajouter la même ligne à chaque exécution, cassant l’idempotence :

# ❌ Sans regexp : la ligne est ajoutée à chaque exécution si "line" ne matche jamais exactement une ligne existante
- name: Ajouter une ligne (mauvaise pratique)
  ansible.builtin.lineinfile:
    path: /etc/sysctl.conf
    line: "vm.swappiness=10"

# ✅ Avec regexp : Ansible trouve la ligne existante (quelle que soit sa valeur actuelle) et la remplace
- name: Ajouter une ligne (bonne pratique)
  ansible.builtin.lineinfile:
    path: /etc/sysctl.conf
    line: "vm.swappiness=10"
    regexp: "^vm.swappiness="

Le réflexe à prendre : dès que vous utilisez lineinfile pour modifier un réglage existant plutôt qu’ajouter une ligne totalement nouvelle, pensez systématiquement au regexp.

Ce qu’il faut retenir

  • template : pour un fichier entier, propre à votre application.
  • lineinfile : pour une seule ligne, dans un fichier partagé avec d’autres réglages.
  • blockinfile : pour un bloc de plusieurs lignes, identifiable et gérable indépendamment du reste du fichier.
  • regexp avec lineinfile est ce qui garantit l’idempotence — sans lui, la ligne peut être dupliquée à chaque exécution.