revision.devops

Linux : administration et troubleshooting

C'est le cœur du poste. L'entretien te mettra presque sûrement devant un scénario de panne. Ce qu'on attend : une démarche méthodique, pas une liste de commandes récitées.

La démarche face à un serveur lent

Ne redémarre pas en premier. Mesure, dans cet ordre :

  1. Ce qui a changé : déploiement récent, pic de trafic, cron, mise à jour.
  2. Charge et CPU : uptime, top. Le load average se lit par rapport au nombre de cœurs (nproc). Un load de 8 sur 8 cœurs, c'est plein. Sur 32 cœurs, c'est calme.
  3. Mémoire : free -h. La colonne available compte, pas free. Le buff/cache est rendu dès qu'un processus en a besoin.
  4. Disque : iostat -x 1 (colonne %util et await), et %wa dans top. Un iowait élevé avec un CPU qui ne fait rien, c'est le disque qui bloque.
  5. Réseau : ss -s, ss -tan state established | wc -l, erreurs dans ip -s link.
  6. Logs : journalctl -p err -S "1 hour ago", dmesg -T | tail.

Brendan Gregg appelle ça la méthode USE : pour chaque ressource, regarder Utilization, Saturation, Errors.

systemd

systemctl status nginx          # état, PID, dernières lignes de log
systemctl restart nginx
systemctl enable --now nginx    # démarrage au boot + maintenant
systemctl list-units --failed   # tout ce qui est en échec
systemctl daemon-reload         # après modif d'un fichier .service
journalctl -u nginx -f          # suivre les logs du service
journalctl -xeu nginx           # fin des logs avec explications
journalctl -b -1                # logs du boot précédent

Un fichier de service minimal, dans /etc/systemd/system/monapp.service :

[Unit]
Description=Mon application
After=network-online.target

[Service]
User=monapp
ExecStart=/opt/monapp/bin/server
Restart=on-failure
RestartSec=5
Environment=PORT=8080

[Install]
WantedBy=multi-user.target

Pour modifier un service fourni par un paquet sans toucher au fichier d'origine : systemctl edit nginx crée un override dans /etc/systemd/system/nginx.service.d/.

Processus et mémoire

ps aux --sort=-%mem | head       # plus gros consommateurs de RAM
ps aux --sort=-%cpu | head
pstree -p                        # arbre des processus
lsof -p 1234                     # fichiers ouverts par un PID
strace -p 1234                   # appels système en direct
vmstat 1                         # r = file d'attente CPU, si = swap in, so = swap out
dmesg -T | grep -i oom           # le noyau a-t-il tué un processus ?

Signaux à connaître :

SignalNuméroEffet
SIGTERM15Arrêt propre, le processus peut nettoyer. C'est le défaut de kill.
SIGKILL9Arrêt brutal par le noyau, rien n'est nettoyé. En dernier recours.
SIGHUP1Souvent utilisé pour recharger la config (nginx, sshd).

Un processus en état D (uninterruptible sleep) attend une I/O. Même kill -9 n'y fait rien : il faut régler le problème d'I/O (NFS bloqué, disque mourant).

Un processus zombie (Z) est terminé mais son parent n'a pas lu son code de sortie. Il ne consomme rien sauf une entrée dans la table des processus. On ne le tue pas, on agit sur le parent.

Disque et stockage

df -h                    # espace par système de fichiers
df -i                    # inodes : plein même avec de l'espace libre
du -sh /var/* | sort -h  # qui prend la place
ncdu /var                # interactif, plus confortable
lsof +L1                 # fichiers supprimés encore ouverts
findmnt                  # points de montage
lsblk                    # disques et partitions

Le piège classique : df dit 100 %, du trouve beaucoup moins. Un fichier a été supprimé (souvent un log énorme avec rm) mais un processus le tient encore ouvert. L'espace n'est libéré qu'à la fermeture. lsof +L1 le montre. Solution : redémarrer ou recharger le processus. Pour vider un log sans ce problème : truncate -s 0 fichier.log ou > fichier.log.

LVM

Couches : disque physique (PV), puis groupe de volumes (VG), puis volume logique (LV).

pvs; vgs; lvs                         # état des trois couches
pvcreate /dev/sdb
vgextend vg_data /dev/sdb             # ajouter un disque au groupe
lvextend -r -L +10G /dev/vg_data/lv_app   # -r redimensionne aussi le FS

ext4 peut s'agrandir à chaud et se réduire seulement démonté. XFS s'agrandit à chaud (xfs_growfs) mais ne se réduit jamais.

Réseau

ip a                       # adresses
ip r                       # routes
ss -tulpn                  # ports en écoute et processus associé
ss -tan                    # connexions TCP
dig +short exemple.fr      # résolution DNS
dig @8.8.8.8 exemple.fr    # tester un autre résolveur
curl -vI https://site      # en-têtes, TLS, redirections
nc -zv host 5432           # le port est-il joignable ?
tcpdump -i eth0 -nn port 443
traceroute / mtr host

Méthode pour « l'appli n'est pas joignable » : DNS résout-il ? Le port écoute-t-il en local (ss -tulpn) ? Sur quelle interface (127.0.0.1 ou 0.0.0.0) ? Le pare-feu local laisse-t-il passer (iptables -L -n, nft list ruleset, firewall-cmd --list-all) ? Le pare-feu cloud ? Ta formation réseau est un atout ici, appuie-toi dessus.

Permissions et utilisateurs

chmod 640 fichier       # rw- r-- ---
chmod u+x script.sh
chown app:app -R /opt/app
umask                   # droits par défaut à la création
visudo                  # éditer sudoers sans casser la syntaxe
id user; groups user

Bits spéciaux : setuid (chmod u+s, s'exécute avec les droits du propriétaire, comme passwd), setgid sur un dossier (les fichiers créés héritent du groupe), sticky bit (/tmp : chacun ne supprime que ses fichiers).

SELinux (RHEL, Rocky, Alma)

Renault tourne probablement sur du RHEL. Si un service refuse d'accéder à un fichier alors que les droits Unix sont bons, pense à SELinux.

getenforce                         # Enforcing, Permissive, Disabled
ausearch -m avc -ts recent         # refus récents
ls -Z /var/www                     # contextes
restorecon -Rv /var/www            # remettre les contextes par défaut
setsebool -P httpd_can_network_connect on

Désactiver SELinux n'est pas une réponse acceptable en entretien. Corriger le contexte, oui.

Liens

  • Lien dur (ln a b) : un deuxième nom pour le même inode. Supprimer l'un n'efface pas les données. Impossible entre deux systèmes de fichiers ou sur un dossier.
  • Lien symbolique (ln -s a b) : un fichier qui contient un chemin. Cassé si la cible disparaît.

Démarrage du système

BIOS/UEFI, puis le chargeur GRUB, puis le noyau et l'initramfs, puis systemd (PID 1), qui atteint une cible (multi-user.target ou graphical.target). Si le serveur ne boote plus après une modif de /etc/fstab, on passe en mode rescue et on corrige la ligne. L'option nofail évite qu'un disque absent bloque le démarrage.

Logs et rotation

  • /var/log/messages (RHEL) ou /var/log/syslog (Debian).
  • /var/log/secure ou /var/log/auth.log pour les connexions.
  • logrotate, configuré dans /etc/logrotate.d/, gère la rotation. copytruncate évite d'avoir à signaler le processus, au prix de quelques lignes perdues possibles.

Paquets

Debian/UbuntuRHEL/Rocky
apt update && apt upgradednf upgrade
apt install xdnf install x
dpkg -lrpm -qa
apt-cache policy xdnf info x

Questions d'entretien à préparer

  • Un serveur est lent, ta démarche ? (voir plus haut, cite la méthode USE)
  • Le disque est plein mais du ne trouve rien ?
  • Différence entre kill -15 et kill -9 ?
  • Un service ne démarre pas au boot, comment tu investigues ?
  • Comment agrandir un FS sans coupure ?
  • Que se passe-t-il quand tu fais ssh serveur ? (DNS, TCP 22, échange de clés, authentification par clé ou mot de passe, ouverture du shell)
  • Le load est à 30 mais le CPU est à 5 %, que regardes-tu ? (iowait et processus en état D)