Mini-test 3

Non-interactif

Modifier des fichiers de config sans intervention humaine

8 questions + partie avancee

3 strategies non-interactif schema bonhomme idempotence (avance)

Cliquez Voir la solution sur chaque slide

← → naviguer · S solution · M manuel · R recommencer

Question 1 / 8 3 strategies a connaitre

3 strategies pour editer un fichier de config

Avant de plonger dans la pratique : sachez nommer et choisir entre les 3 strategies d'edition de fichiers de config dans un script.

Nommez les 3 strategies et donnez un exemple de cas ou chacune est appropriee :

Strategie Quand l'utiliser Outil bash
1. Ecraser avec sa version On controle entierement le contenu (versionne dans fichiers-config/) cp ou cat ... >
2. Ajouter a la fin Petits ajouts non destructifs (un bloc fail2ban a la suite) tee -a, >>
3. Modif chirurgicale Changer une seule valeur dans un fichier existant qu'on respecte sed -i

Bonus : il existe aussi debconf-set-selections pour repondre a l'avance aux dialogues debconf des paquets (mots de passe MySQL, acceptations de licence, etc.).

Question 2 / 8 associer commandes -> strategie

Quelles commandes pour chaque strategie ?

Vous venez de nommer les 3 strategies. Maintenant on les incarnent avec les outils bash correspondants. Glissez chaque commande dans la strategie qu'elle implemente.

Une commande peut aller dans une seule strategie. Plusieurs commandes par strategie. Cliquez sur une etiquette deposee pour la retirer.

cp source dest
cat src > dest
tee dest <<EOF ...
tee -a dest <<EOF ...
echo "..." >> dest
cat src >> dest
sed -i 's/x/y/' dest
sed -i.bak 's/x/y/' dest
mv source dest
vim dest
1. Ecraser avec sa version
on prend le controle total du fichier
2. Ajouter a la fin
on respecte ce qui est deja la
3. Modif chirurgicale
on change UNE ligne precise

Strategie 1 - Ecraser : cp, cat > dest, tee <<EOF (heredoc sans -a). On ne respecte pas l'existant, on remplace.

Strategie 2 - Ajouter a la fin : tee -a, echo >>, cat src >> dest. Le double chevron ou le -a est le marqueur. L'existant reste, on ajoute apres.

Strategie 3 - Modif chirurgicale : sed -i (et sa variante sed -i.bak qui sauvegarde l'original). On respecte le fichier et on touche juste a une ligne ciblee.

Pourquoi pas les autres ?

Memo : dans un script de provisionnement, regle quelle strategie avant de regarder quel outil. Apres seulement, on choisit l'outil. Et on prefere tee a > ou >> quand on a besoin de sudo (la redirection echoue avec sudo, tee fonctionne).

Question 3 / 8 strategie 1 - ecraser

Pre-positionner un fichier complet

Vous avez prepare un ircd-hybrid.conf de reference, versionne a cote de votre script dans ./fichiers-config/ircd-hybrid.conf. Vous voulez l'installer comme fichier de config du serveur.

Donnez les 2 commandes qui :

# 1. Sauvegarde datee de l'existant
sudo cp /etc/ircd-hybrid.conf /etc/ircd-hybrid.conf.bak.$(date +%Y%m%d-%H%M%S)

# 2. Copier le fichier de reference par dessus
sudo cp ./fichiers-config/ircd-hybrid.conf /etc/ircd-hybrid.conf

# Bonus : valider les permissions
sudo chown root:root /etc/ircd-hybrid.conf
sudo chmod 644 /etc/ircd-hybrid.conf

Pourquoi sauvegarder d'abord ? Si la copie casse quelque chose, vous voulez pouvoir revenir au fichier original. La suffixe avec $(date +...) empeche d'ecraser une vieille sauvegarde en relancant le script.

Variante en heredoc si on ne veut pas de fichier separe :

sudo tee /etc/ircd-hybrid.conf > /dev/null <<'EOF'
listen=YES
anonymous_enable=NO
local_enable=YES
enable_ssl=yes
EOF

Question 4 / 8 strategie 2 - ajouter a la fin

Ajouter un bloc fail2ban a jail.local

L'admin est dans son repertoire de projet et veut ajouter un bloc a la fin du fichier /etc/fail2ban/jail.local, sans toucher au reste. Voici la situation :
~/projet-ircd$ sudo tee -a \ /etc/fail2ban/\ jail.local \ <<'EOF' L'admin pwd = ~/projet-ircd heredoc (texte inline) [ircd-hybrid] enabled = true port = 6667 logpath = ... EOF tee -a (append) / etc/ fail2ban/ jail.local [DEFAULT] bantime = 1h findtime = 10m maxretry = 5 [sshd] enabled = true ^ existant ajout v [ircd-hybrid] enabled = true port = 6667 logpath = ... L'admin est dans ~/projet-ircd. Le heredoc (texte inline) est lu par tee -a et ajoute a la fin de /etc/fail2ban/jail.local

Donnez la commande bash qui ajoute ce bloc a la fin du fichier /etc/fail2ban/jail.local :

TEE(1) - extrait du manuel
NAME
       tee - lit l'entree standard et ecrit dans des fichiers ET stdout

SYNOPSIS
       tee [OPTIONS] [FICHIER...]

OPTIONS
       -a, --append      ajouter (append) au lieu d'ecraser
       -i, --ignore-interrupts
                          ignorer Ctrl-C (utile dans un pipe)

PARTICULARITE
       tee est utile pour ecrire dans un fichier qui necessite sudo
       depuis un pipe. (Avec >>, la redirection est faite par le shell
       AVANT sudo, donc >> echoue sur les fichiers proteges.)

EXEMPLES
       # Ecraser un fichier (silencer stdout avec /dev/null)
       echo "ligne" | sudo tee /etc/config > /dev/null

       # Ajouter a la fin
       echo "ligne" | sudo tee -a /etc/config > /dev/null

       # Avec heredoc multilignes
       sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'
       [ircd-hybrid]
       enabled = true
       EOF
BASH(1) - extrait : redirection & heredoc
REDIRECTION
       > fichier          ecrase
       >> fichier         ajoute a la fin (append)
       2> fichier         redirige stderr
       &> fichier         redirige stdout ET stderr
       2>&1              fusionne stderr dans stdout
       > /dev/null        ignorer la sortie

PIEGE AVEC SUDO
       sudo cmd >> /fichier-protege   # echoue !
       Raison : le shell ouvre /fichier-protege AVANT d'invoquer sudo,
       donc l'ouverture se fait avec les droits de l'utilisateur.
       Solution : passer par "sudo tee -a" (la redirection est interne).

HEREDOC (here-document)
       <<DELIMITEUR      lit du texte inline jusqu'a la ligne DELIMITEUR
       <<'DELIMITEUR'    delimiteur quote -> PAS d'expansion de variables
                          (utile pour les fichiers contenant $, `, etc.)
       <<-DELIMITEUR     accepte les TABS de retrait (mais pas les espaces)

EXEMPLE complet
       sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'
       [ircd-hybrid]
       enabled = true
       port    = 6667
       EOF
sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'

[ircd-hybrid]
enabled = true
port = 6667
logpath = /var/log/ircd-hybrid/ircd.log
EOF

Decomposition :

Equivalent plus court pour une seule ligne :

echo "[ircd-hybrid]" | sudo tee -a /etc/fail2ban/jail.local
# Mais pour un bloc de plusieurs lignes, le heredoc est plus propre

Probleme cache : si on relance le script, ce bloc sera ajoute une deuxieme fois. On verra comment regler ca dans la partie avancee a la fin du mini-test.

Question 5 / 8 strategie 3 - sed chirurgical

Modifier UNE ligne avec sed

Le fichier /etc/ircd-hybrid.conf contient la ligne suivante (avec un # qui la rend inactive) :
#enable_ssl=yes

Vous voulez decommenter cette ligne (retirer le #) avec une seule commande sed dans votre script. Donnez la commande, et expliquez chaque element.

SED(1) - extrait du manuel
NAME
       sed - stream editor (editeur de flux ligne par ligne)

SYNOPSIS
       sed [OPTIONS] 'COMMANDE' [FICHIER...]

OPTIONS frequentes
       -i            edition in-place (modifie le fichier)
       -i.bak        sauvegarde l'original sous .bak avant
       -n            ne pas imprimer par defaut (avec p pour selectionner)
       -E            regex etendues (sans backslash devant + ? | ())
       -e CMD        plusieurs commandes (peut etre repete)

COMMANDE substitution
       s/MOTIF/REMPLACEMENT/FLAGS

       FLAGS
            g     toutes les occurrences (defaut : la 1ere seulement)
            i     insensible a la casse
            2     2e occurrence seulement

ANCRES utiles
       ^     debut de ligne
       $     fin de ligne
       .     un caractere
       .*    zero ou plus de caracteres

ADRESSES (selectionner les lignes a traiter)
       /MOTIF/ s/.../.../      seulement les lignes qui matchent
       3 s/.../.../            seulement la ligne 3
       3,7 s/.../.../          lignes 3 a 7

EXEMPLES
       # Decommenter une ligne precise
       sudo sed -i 's/^#enable_ssl=yes/enable_ssl=yes/' /etc/ircd-hybrid.conf

       # Avec backup .bak (securite)
       sudo sed -i.bak 's/^#enable_ssl/enable_ssl/' /etc/ircd-hybrid.conf

       # Changer un parametre (n'importe quelle valeur)
       sudo sed -i 's/^Port .*/Port 2222/' /etc/ssh/sshd_config

       # Decommenter (espace optionnel apres #)
       sudo sed -i 's/^# *PasswordAuthentication/PasswordAuthentication/' /etc/ssh/sshd_config

       # Astuce delimiteur : si le motif contient des /, utiliser un autre delimiteur
       sudo sed -i 's|/var/log/old|/var/log/new|' /etc/syslog.conf
sudo sed -i 's/^#enable_ssl=yes/enable_ssl=yes/' /etc/ircd-hybrid.conf

Decomposition :

Variantes utiles :

# Activer une option pas encore presente (apres une ligne specifique)
sudo sed -i '/^[General]/a enable_ssl=yes' /etc/ircd-hybrid.conf

# Remplacer une valeur quelconque
sudo sed -i 's/^max_clients=.*/max_clients=50/' /etc/ircd-hybrid.conf

# Tester d'abord SANS -i (afficher le resultat)
sed 's/^#enable_ssl=yes/enable_ssl=yes/' /etc/ircd-hybrid.conf | less

Question 6 / 8 retirer l'interactivite - niveaux 1 et 2

apt sans aucun prompt

Vous lancez votre script et apt vous demande "Do you want to continue [Y/n]?" puis plus tard "A new version of /etc/sshd_config is available. Replace?". Comment empecher TOUS les prompts ?

Donnez :

APT-GET(8) - extrait du manuel
NAME
       apt-get - utilitaire APT en ligne de commande (scriptable)

SYNOPSIS
       apt-get [OPTIONS] COMMANDE [PAQUET...]

COMMANDES principales
       update           rafraichit la liste des paquets disponibles
       install          installer ou mettre a niveau un paquet
       upgrade          mettre a niveau tous les paquets installes
       dist-upgrade     comme upgrade mais peut ajouter/retirer des paquets
       remove           retirer un paquet (conserve les fichiers de config)
       purge            retirer + effacer les fichiers de config
       autoremove       retirer les paquets installes en dependance et non utilises

OPTIONS utiles en script
       -y, --yes                repond "yes" automatiquement aux prompts
       -q, --quiet              moins de sortie (utile dans les logs)
       --no-install-recommends  n'installer que les vraies dependances
       -o Dpkg::Options::="..."  passer une option a dpkg

CONFLITS DE CONFIG (fichiers /etc/*)
       Quand un paquet propose un nouveau /etc/foo.conf et que vous l'aviez modifie,
       dpkg vous demande quoi faire. Pour scripter, on choisit AVANT :

       -o Dpkg::Options::="--force-confdef"
            preserver le defaut decide par le mainteneur
       -o Dpkg::Options::="--force-confold"
            garder l'ANCIEN fichier (votre version modifiee)
       -o Dpkg::Options::="--force-confnew"
            ecraser avec le NOUVEAU fichier du paquet

VARIABLES D'ENVIRONNEMENT
       DEBIAN_FRONTEND=noninteractive
            desactive TOUS les dialogues debconf (questions
            "voulez-vous installer X comme service ?")
       APT_LISTCHANGES_FRONTEND=none
            desactive l'affichage des changelogs

EXEMPLES
       # Installation completement silencieuse
       export DEBIAN_FRONTEND=noninteractive
       sudo apt-get install -y \
            -o Dpkg::Options::="--force-confdef" \
            -o Dpkg::Options::="--force-confold" \
            ircd-hybrid

       # Inline (frontend juste pour cette commande)
       sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ircd-hybrid

       # Minimaliste (pas de paquets recommandes)
       sudo apt-get install -y --no-install-recommends nginx
export DEBIAN_FRONTEND=noninteractive
sudo apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" ircd-hybrid

Niveau 1 : switch -y

Repond "yes" aux questions de confirmation classiques d'apt ("Do you want to continue?"). Sans ca, le script s'arrete en attendant votre touche.

Niveau 2 : DEBIAN_FRONTEND=noninteractive

Variable d'environnement qui dit au gestionnaire de paquets Debian/Ubuntu : "pas d'interface utilisateur, pas de question, choisis les defauts". Couvre les dialogues debconf (les ecrans bleus qui demandent par exemple un mot de passe MySQL).

Niveau 3 (avance) : les options Dpkg

Toujours utiliser apt-get dans les scripts (interface stable), pas apt (interface utilisateur qui peut changer).

Question 7 / 8 retirer l'interactivite - niveau 3

Le paquet pose une question debconf

Quand vous installez mysql-server, un ecran bleu vous demande le mot de passe root MySQL. Vous voulez automatiser ca.

Donnez la sequence de commandes pour :

DEBCONF-SET-SELECTIONS(1) - extrait du manuel
NAME
       debconf-set-selections - precharger des reponses dans la base debconf

SYNOPSIS
       debconf-set-selections [--checkonly] [--verbose] [FICHIER]

DESCRIPTION
       Permet de repondre AVANT installation aux questions debconf
       (les ecrans bleus de configuration). Lit des lignes au format :

       PAQUET   QUESTION/CLE   TYPE   VALEUR

TYPES (champ 3)
       string             texte libre (ex: nom, mot de passe)
       password           identique mais pour les mdp
       boolean            true | false
       select             un choix parmi plusieurs
       multiselect        plusieurs choix

DECOUVRIR les cles d'un paquet
       # Installer debconf-utils une fois
       sudo apt-get install -y debconf-utils

       # Voir TOUTES les cles + valeurs courantes d'un paquet installe
       sudo debconf-get-selections | grep mysql-server

EXEMPLES
       # Format ligne directe
       echo 'mysql-server mysql-server/root_password password motdepasse' | \
            sudo debconf-set-selections

       # Avec heredoc multi-lignes
       sudo debconf-set-selections <<EOF
       mysql-server mysql-server/root_password         password motdepasse
       mysql-server mysql-server/root_password_again   password motdepasse
       EOF

       # Puis installation silencieuse
       export DEBIAN_FRONTEND=noninteractive
       sudo apt-get install -y mysql-server

PIEGES
       - debconf-set-selections doit etre lance AVANT apt-get install
       - DEBIAN_FRONTEND=noninteractive doit aussi etre exporte
       - Les espaces entre les champs sont libres (tabs ou espaces)
export DEBIAN_FRONTEND=noninteractive

# 1. Pre-positionner les reponses
sudo debconf-set-selections <<EOF
mysql-server mysql-server/root_password password monMotDePasse
mysql-server mysql-server/root_password_again password monMotDePasse
EOF

# 2. Installer normalement
sudo apt-get install -y mysql-server

Comment trouver les bonnes cles debconf ?

# Apres avoir installe le paquet manuellement une fois, on regarde
# les questions posees :
sudo debconf-get-selections | grep mysql-server

Hierarchie complete pour retirer l'interactivite :

  1. Switches -y, --yes, --assume-yes
  2. DEBIAN_FRONTEND=noninteractive
  3. Bas-niveau : useradd au lieu de adduser, chpasswd au lieu de passwd
  4. Pre-positionner les fichiers de config avant l'install
  5. debconf-set-selections pour repondre a l'avance aux dialogues
  6. Reflexe : man de la commande pour --batch, --quiet, --auto...
  7. Dernier recours : expect (simule un humain qui tape)

Question 8 / 8 tout assembler

Assembler dans un script complet

Vous voulez ecrire un bout de script qui :
  1. met a jour apt sans aucun prompt
  2. installe ircd-hybrid
  3. active enable_ssl dans /etc/ircd-hybrid.conf
  4. ajoute un bloc [ircd-hybrid] a /etc/fail2ban/jail.local (idempotent)
  5. redemarre les deux services

Ecrivez le bout de script (pas besoin de la banniere ni du shebang) :

export DEBIAN_FRONTEND=noninteractive
set -e

# 1. Mise a jour et installation
sudo apt-get update -y
sudo apt-get install -y ircd-hybrid

# 2. Activer enable_ssl (strategie sed - ligne deja presente, commentee)
sudo sed -i 's/^#enable_ssl=yes/enable_ssl=yes/' /etc/ircd-hybrid.conf

# 3. Ajouter le bloc fail2ban (strategie tee -a, idempotente)
if ! grep -q '^\[ircd-hybrid\]' /etc/fail2ban/jail.local 2>/dev/null; then
    sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'

[ircd-hybrid]
enabled = true
port = 21
logpath = /var/log/ircd-hybrid.log
EOF
fi

# 4. Redemarrer les services
sudo systemctl restart ircd-hybrid
sudo systemctl restart fail2ban

echo "Configuration terminee."

Astuces du pro :

Partie avancee

Aller plus loin

Idempotence, securite, robustesse :
les techniques pour des scripts qui ne cassent rien quand on les relance

Ces questions vont plus loin que l'examen.
Elles construisent des reflexes de "vrai" admin.

Question avancee 1 idempotence : detecter avant d'agir

Rendre l'ajout idempotent

Rappel de Q3 : on ajoute un bloc [ircd-hybrid] a la fin de /etc/fail2ban/jail.local avec tee -a. Si on relance le script (parce qu'on veut corriger une autre etape), le bloc est ajoute une deuxieme fois. Resultat : un fichier qui contient deux fois le meme bloc, et fail2ban refusera de demarrer.

Modifiez la commande pour qu'elle detecte si le bloc est deja present et n'ajoute rien dans ce cas. Donnez la commande complete (avec la detection).

Indice : la cle est de tester avant d'agir. Quelle commande retourne un code de sortie 0 ou non-0 selon qu'un motif est dans un fichier ?

GREP(1) - extrait du manuel
NAME
       grep - chercher des motifs dans des fichiers

SYNOPSIS
       grep [OPTIONS] MOTIF [FICHIER...]

OPTIONS frequentes
       -q, --quiet          aucune sortie - utilise UNIQUEMENT le code de retour
       -F, --fixed-strings  motif litteral (pas de regex)
       -E, --extended-regexp regex etendues
       -i, --ignore-case    insensible a la casse
       -v, --invert-match   inverser (lignes qui NE matchent PAS)
       -c, --count          compter les lignes
       -n, --line-number    afficher les numeros de ligne
       -r, --recursive      recursif dans un dossier
       -l, --files-with-matches  juste les noms de fichiers
       -x, --line-regexp    match la ligne entiere

CODES DE SORTIE (cle pour scripter)
       0   au moins un match trouve
       1   aucun match
       2   erreur (fichier introuvable, etc.)

       Donc en bash : "if grep -q ... ; then ..." marche sans piping
       ni $(...). C'est l'idiome standard pour "tester si X est dans un fichier".

ANCRES (regex de base)
       ^MOTIF     debut de ligne
       MOTIF$     fin de ligne
       ^MOTIF$    ligne entiere

       Caracteres a echapper dans le motif : [ ] . * + ? ( ) | { } $ ^
       Avec -F, tout est litteral, plus besoin d'echapper.

EXEMPLES (idempotence)
       # Ajouter un bloc seulement s'il n'existe pas deja
       if ! grep -q '^\[ircd-hybrid\]' /etc/fail2ban/jail.local 2>/dev/null; then
           sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'
       [ircd-hybrid]
       enabled = true
       EOF
       fi

       # Variante : grep -qF si le motif contient des caracteres regex penibles
       if ! grep -qF '[ircd-hybrid]' /etc/fail2ban/jail.local 2>/dev/null; then
           ...
       fi

       # Cibler la ligne entiere (eviter les faux positifs)
       if ! grep -qx 'PasswordAuthentication no' /etc/ssh/sshd_config; then
           ...
       fi

La technique : grep -q + if !

if ! grep -q '^\[ircd-hybrid\]' /etc/fail2ban/jail.local 2>/dev/null; then
    sudo tee -a /etc/fail2ban/jail.local > /dev/null <<'EOF'

[ircd-hybrid]
enabled = true
port = 6667
logpath = /var/log/ircd-hybrid/ircd.log
EOF
fi

Decomposition :

Le terme : idempotence

Une operation est idempotente si la rejouer N fois donne le meme resultat que la jouer une seule fois. En administration systeme, c'est une qualite essentielle : on doit pouvoir relancer un script (apres un crash, une correction) sans craindre de tout casser.

Autres patterns d'idempotence dans la vraie vie :

# mkdir -p ne genere pas d'erreur si le repertoire existe deja
mkdir -p /var/backups/ircd

# useradd n'echoue plus si le -f est mis (force)
id -u mqtt-iot &>/dev/null || sudo adduser --system mqtt-iot

# systemctl is-enabled avant enable
systemctl is-enabled ircd-hybrid || sudo systemctl enable ircd-hybrid

# Marker file : ne refaire qu'une fois
if [ ! -f /var/lib/mon-script.done ]; then
    # ... operations
    touch /var/lib/mon-script.done
fi

Ces outils existent precisement parce que rendre un script idempotent est la bonne pratique fondamentale en administration. C'est aussi ce qu'Ansible et les outils de configuration management font automatiquement.

Bilan

Ce que vous venez de pratiquer

Touche R pour recommencer ce mini-test

« Retour aux mini-tests