
ansible.builtin.blockinfile insère ou met à jour un bloc multi-lignes dans un fichier existant, avec idempotence garantie via des markers automatiques. C'est le module qui comble le trou entre lineinfile: (1 ligne) et template: (fichier complet).
Cas d'usage typiques : ajouter 3-10 lignes de durcissement dans /etc/ssh/sshd_config.d/99-ansible.conf, déposer un bloc d'aliases dans /etc/profile.d/, gérer une section custom dans un fichier que vous ne contrôlez pas entièrement.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le rôle des markers
# BEGIN ANSIBLE MANAGED BLOCK/# END ANSIBLE MANAGED BLOCK. - Comment personnaliser le marker pour gérer plusieurs blocs dans le même fichier.
- Quand
blockinfile:est préférable àlineinfile:(multi-lignes) ou àtemplate:(fichier non possédé). - Le piège des commentaires de marker dans des fichiers où
#n'est pas un commentaire.
Prérequis
Section intitulée « Prérequis »- Connaître les modules
copy:etlineinfile:,blockinfile:se positionne entre les deux.
Le mécanisme des markers
Section intitulée « Le mécanisme des markers »Quand vous insérez un bloc avec blockinfile:, Ansible encadre votre bloc avec deux markers :
# BEGIN ANSIBLE MANAGED BLOCKPermitRootLogin noPasswordAuthentication noMaxAuthTries 3# END ANSIBLE MANAGED BLOCKAu prochain run, Ansible cherche les markers, remplace tout ce qui est entre les deux par le nouveau bloc, et regénère les markers. Conséquence : idempotence garantie, jamais de duplication.
Ne pas modifier les markers à la main entre deux runs, Ansible perdrait le repère et empilerait un nouveau bloc.
Exemple : durcissement sshd
Section intitulée « Exemple : durcissement sshd »- name: Durcissement sshd via blockinfile ansible.builtin.blockinfile: path: /etc/ssh/sshd_config.d/99-ansible.conf create: true mode: "0600" block: | PermitRootLogin no PasswordAuthentication no MaxAuthTries 3 ClientAliveInterval 300 marker: "# {mark} HARDENING ANSIBLE" notify: Reload sshdcreate: true crée le fichier s'il n'existe pas, pratique pour les drop-in configs dans /etc/ssh/sshd_config.d/.
marker: "# {mark} HARDENING ANSIBLE" personnalise le marker. {mark} est remplacé par BEGIN ou END. Résultat dans le fichier :
# BEGIN HARDENING ANSIBLEPermitRootLogin no…# END HARDENING ANSIBLEPourquoi customiser le marker ? Si vous gérez plusieurs blocs dans le même fichier (un pour le hardening, un pour les aliases utilisateur, un pour la perf tuning), chaque bloc doit avoir son marker unique, sinon Ansible ne sait plus lequel mettre à jour.
Insertion à un endroit précis, insertafter: / insertbefore:
Section intitulée « Insertion à un endroit précis, insertafter: / insertbefore: »Par défaut, blockinfile: ajoute à la fin du fichier (EOF). Pour insérer après une ligne précise :
- name: Ajouter un bloc apres la ligne PORT ansible.builtin.blockinfile: path: /etc/myapp/config.ini insertafter: '^Port=' block: | LogLevel = INFO LogPath = /var/log/myapp/ marker: "# {mark} LOGGING"Si la regex ne matche pas et qu'on utilise insertafter: EOF (défaut), le bloc est ajouté en fin de fichier. Si la regex est définie et ne matche pas, le bloc est aussi ajouté en fin (comportement par défaut Ansible), pour échouer dans ce cas, ajouter une vérification préalable.
Suppression, state: absent
Section intitulée « Suppression, state: absent »- name: Retirer le bloc de durcissement ansible.builtin.blockinfile: path: /etc/ssh/sshd_config.d/99-ansible.conf marker: "# {mark} HARDENING ANSIBLE" state: absentAnsible cherche les markers BEGIN HARDENING ANSIBLE et END HARDENING ANSIBLE et supprime tout entre les deux (markers compris). Le reste du fichier est intact.
Marker dans des fichiers où # n'est pas un commentaire
Section intitulée « Marker dans des fichiers où # n'est pas un commentaire »Pour un fichier YAML, JSON ou XML, le marker # BEGIN… est invalide syntaxiquement.
# Pour un YAML : commentaire = "#" (OK)marker: "# {mark} ANSIBLE"
# Pour un XML : commentaire = "<!-- ... -->"marker: "<!-- {mark} ANSIBLE -->"
# Pour un fichier SQL :marker: "-- {mark} ANSIBLE"Toujours adapter le marker au format du fichier cible, sinon le fichier devient cassé.
Comparaison lineinfile vs blockinfile vs template
Section intitulée « Comparaison lineinfile vs blockinfile vs template »| Cas | Module recommandé | Raison |
|---|---|---|
1 ligne (net.ipv4.ip_forward = 1) | lineinfile: | Le plus simple, regex pour matching |
| 3-10 lignes liées (bloc d'options) | blockinfile: | Markers, idempotence, suppression facile |
Fichier complet (nginx.conf) | template: | Interpolation Jinja2, validate, backup |
| Plusieurs blocs dans un fichier | blockinfile: × N | Un marker custom par bloc |
| Fichier qu'on ne possède pas (système) | blockinfile: | On modifie sans tout réécrire |
Pièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Fix |
|---|---|---|
| 2 blocs empilés à chaque run | Marker par défaut + 2 tâches dans le playbook | Marker unique par bloc (# {mark} BLOC1, # {mark} BLOC2) |
| Fichier YAML/JSON cassé | Marker # … injecté dans un format où # est invalide | Adapter le marker (-- {mark} pour SQL, <!-- {mark} --> pour XML) |
Bloc ajouté à EOF au lieu de l'endroit voulu | insertafter: regex ne matche pas | Tester la regex avec grep -E avant |
blockinfile: sur fichier inexistant échoue | create: false (défaut) | Ajouter create: true |
À retenir
Section intitulée « À retenir »blockinfile:= idéal pour 3-10 lignes liées dans un fichier existant.- Markers garantissent l'idempotence, ne jamais les modifier à la main.
- Marker custom (
marker: "# {mark} MY_BLOCK") obligatoire si plusieurs blocs dans un fichier. create: truecrée le fichier s'il n'existe pas, utile pour les drop-in configs.- Adapter le format du marker au type de fichier (
#,--,<!-- -->, etc.).
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »Cette page a un lab d'accompagnement : labs/modules-fichiers/blockinfile/ dans stephrobert/ansible-training.
Challenge, sur db1.lab :
- Créer
/etc/profile.d/aliases-rhce.sh(create: true, mode0644). - Insérer un bloc d'aliases (
ll,gs,ports) avec marker# {mark} ALIASES RHCE. - Vérifier que 2 runs successifs ne dupliquent pas le bloc.
Validation pytest+testinfra :
ansible-playbook solution.ymlansible-playbook solution.yml # Doit etre ok=1, changed=0pytest -v labs/modules-fichiers/blockinfile/challenge/tests/4 tests vérifient l'existence du fichier, son contenu, la présence des markers et l'idempotence (un seul bloc dans le fichier).