bash trap: Cleaning Up After an Interrupted Script
A script killed mid-execution leaves a temp file or lockfile behind, unless trap catches the signal first. SIGKILL remains impossible to intercept.
A script killed mid-execution leaves a temp file or lockfile behind, unless trap catches the signal first. SIGKILL remains impossible to intercept.
A server whose clock drifts by a few minutes silently rejects valid TLS certificates. chronyc tracking reveals in one command what nobody actually monitors.
cloud-init ne s'exécute qu'une fois par instance, un état tracké localement. Cloner une VM sans l'effacer fait croire à cloud-init qu'il a déjà tourné, clés SSH dupliquées à la clé.
Un crash sans core dump n'est pas un mystère : ulimit -c vaut 0 par défaut, et systemd ignore souvent /etc/security/limits.conf pour cette limite.
A crash with no core dump isn't always a mystery: ulimit -c defaults to 0 on most distros, and systemd often ignores /etc/security/limits.conf.
Un serveur dont l'horloge dérive de quelques minutes rejette silencieusement des certificats TLS valides. chronyc tracking révèle en une commande ce que personne ne surveille.
Could not get lock pousse à supprimer le verrou directement. Vérifier quel processus le détient d'abord évite une base de paquets corrompue.
Could not get lock pushes toward deleting the lock directly. Checking which process holds it first avoids a corrupted package database.
Un périphérique listé dans fstab mais absent au boot peut bloquer tout le démarrage. L'option nofail existe pour ça.
A device listed in fstab but absent at boot can block the machine's entire startup. The nofail option exists for this.
Un hard link partage le même inode que l'original, un symlink pointe vers un chemin. C'est pourquoi l'un survit à la suppression de l'original, l'autre non.
A hard link shares the same inode as the original, a symlink points to a path. That difference explains why one survives deleting the original and the other doesn't.
df continue d'afficher l'ancienne taille après un lvextend réussi : agrandir un volume logique LVM ne redimensionne jamais automatiquement le système de fichiers qu'il contient.
df still shows the old size after a successful lvextend: growing an LVM logical volume never automatically resizes the filesystem it contains.
Une commande lancée avec & tourne en arrière-plan mais meurt quand même à la fermeture du terminal : le shell envoie SIGHUP à ses enfants. nohup et disown évitent ça.
Une résolution de nom incohérente entre deux machines pointe souvent vers nsswitch.conf, pas vers le DNS : il définit l'ordre des sources pour hosts, passwd et group.
Inconsistent name resolution between two machines often points to nsswitch.conf, not DNS itself: it defines the order sources are checked for hosts, passwd, and group.
Un processus zombie est déjà mort. Lui envoyer SIGKILL ne fait rien : la vraie cause est un parent qui n'a jamais récupéré son code de sortie.
chmod and chown are correct, yet Permission denied persists. SELinux enforces a second permission system, independent of classic Unix rights: the security context.
chmod et chown corrects, et pourtant Permission denied persiste. SELinux applique un second système de permissions : le contexte de sécurité, indépendant des droits Unix.
Le bit setuid marche sur un binaire compilé mais le kernel l'ignore silencieusement sur un script shell, protection délibérée contre une classe de faille connue.
Écrire dans un répertoire suffit à y supprimer n'importe quel fichier, même d'un autre utilisateur. Le sticky bit sur /tmp casse délibérément cette règle par défaut.
Write permission on a directory normally lets you delete any file inside, even one owned by someone else. The sticky bit on /tmp changes that default rule.
Ajouter du swap aggrave parfois la situation : un système qui thrashe devient inutilisable, souvent pire qu'un processus tué proprement et vite par l'OOM killer.
Adding swap doesn't always buy time before an OOM: a thrashing system becomes unusable, often worse than a process killed cleanly and fast.
/tmp n'est pas nettoyé qu'au reboot : systemd-tmpfiles-clean tourne périodiquement et supprime les fichiers dépassant un âge configuré, reboot ou pas.
/tmp isn't only cleared on reboot: systemd-tmpfiles-clean runs periodically and deletes files past a configured age, reboot or not.
Un script tué en pleine exécution laisse un lockfile derrière lui, sauf si trap intercepte le signal avant. SIGKILL reste impossible à intercepter, quel que soit le trap défini.
Un script fonctionne bien à la main mais crée des fichiers aux permissions différentes lancé par cron. Le coupable est presque toujours un umask différent, pas le script.
A script works fine by hand but creates files with different permissions under cron. The culprit is almost always a different umask, rarely the script.
Editing /etc/sudoers directly risks a syntax error that breaks sudo for everyone, including the person fixing it. visudo validates before writing.
Éditer /etc/sudoers directement risque une erreur de syntaxe qui casse sudo pour tout le monde, y compris pour la corriger. visudo valide avant d'écrire.
cloud-init only runs once per instance, a state tracked locally. Cloning a VM without wiping it makes cloud-init think it already ran, duplicating SSH host keys in the process.
Launching a command with & runs it in the background, but it still dies when the terminal closes: the shell sends SIGHUP to its children. nohup and disown prevent that.
The setuid bit works on a compiled binary but the kernel silently ignores it on a shell script, a deliberate security protection against a known exploit class.
A zombie process is already dead. Sending it SIGKILL does nothing: the real cause is a parent that never collected its exit status.
Une tâche cron qui échoue ne le dit à personne par défaut. Un systemd timer hérite du Restart et de l'historique journalctl du service qu'il déclenche.
A failing cron job doesn't notify anyone by default. A systemd timer inherits the Restart behavior and journalctl history of the service it triggers.
No space left on device while df -h shows 40% free isn't a contradiction: it's never disk space that's exhausted, it's inodes, a distinct and equally finite resource.
No space left on device alors que df -h affiche 40% de libre : ce n'est jamais l'espace disque qui manque, ce sont les inodes, une ressource distincte et finie.
nftables est le défaut depuis des années, mais une couche de compatibilité fait tourner les anciennes règles iptables sans jamais forcer leur migration.
nftables has replaced iptables by default on most distributions for years, but a compatibility layer keeps old rules running without ever truly migrating them.
A disk filling up with no visible file explaining the space often hides a log renamed by rotation, but still open by a process writing into thin air.
Un disque qui se remplit sans qu'aucun fichier visible ne l'explique cache souvent un log renommé par rotation, mais toujours ouvert par un processus qui écrit dans le vide.
set -e n'arrête jamais un script à l'intérieur d'un if ni d'une condition &&. Comprendre les trois options séparément évite le faux sentiment de sécurité.
What set -euo pipefail actually means, flag by flag: set -e never catches an error inside an if or an && condition, and each flag catches something else.
Restart=on-failure ne suffit pas à empêcher un service de boucler indéfiniment. StartLimitBurst est le vrai coupe-circuit, souvent jamais réglé.
Restart=on-failure alone doesn't stop a service from looping forever. StartLimitBurst is the real circuit breaker, and it's rarely configured explicitly.
Augmenter ulimit -n dans limits.conf ne change rien pour un service systemd : LimitNOFILE= dans l'unité prime totalement sur les limites PAM classiques.
Raising ulimit -n in /etc/security/limits.conf changes nothing for a systemd service: LimitNOFILE= in the unit completely overrides classic PAM limits.