Jour 38 Day 38 · mardi 29 septembre 2026 Tuesday 29 September 2026 DevOps Fondamental
Linux pour développeur Linux for developers
Processus et signaux, permissions, pipes, systemd et les commandes qui sauvent : le socle Linux qu'on attend d'un stagiaire dev — et la méthode pour déboguer un serveur qui ne répond plus. Processes and signals, permissions, pipes, systemd and the commands that save the day: the Linux foundation expected from a dev intern — plus the method for debugging a server that stopped responding.
L’essentiel
Vos serveurs tournent sous Linux. Vos conteneurs Docker aussi. Votre CI, votre Raspberry Pi, et 100 % du top 500 des supercalculateurs. Un développeur qui sait se débrouiller dans un shell Linux débogue seul ce que les autres escaladent — c’est exactement ce qu’un recruteur cherche chez un stagiaire.
Deux idées fondatrices structurent tout le système :
- Tout est fichier — les disques (
/dev/sda), les sockets, et même l’état du noyau :/procest un filesystem virtuel où chaque processus a son répertoire (/proc/1234/), oùcat /proc/cpuinfolit les CPU et/proc/meminfola mémoire. Lire, écrire, rediriger : une seule interface pour tout. - Petits outils composables — la philosophie Unix : chaque programme fait une chose bien, le texte est l’interface universelle, et le pipe
|les assemble en chaînes puissantes.grepne sait pas trier,sortne sait pas filtrer — ensemble, ils font de l’analyse de logs.
Comment ça marche
Processus : fork, exec, signaux
Un nouveau processus naît toujours par fork() (le parent se clone) généralement suivi d’exec() (le clone se remplace par le nouveau programme) — c’est ainsi que votre shell lance chaque commande. Chaque processus a un PID ; le tout premier, PID 1 (systemd), démarre le système et adopte les orphelins.
On parle aux processus par signaux :
| Signal | N° | Effet | Interceptable ? |
|---|---|---|---|
| SIGHUP | 1 | terminal fermé / recharger la config | oui |
| SIGINT | 2 | Ctrl+C | oui |
| SIGTERM | 15 | « termine-toi proprement » (défaut de kill) | oui |
| SIGKILL | 9 | mort immédiate, décidée par le noyau | non |
| SIGSEGV | 11 | accès mémoire invalide | oui |
| SIGSTOP / SIGCONT | 19 / 18 | pause / reprise | non / oui |
SIGTERM vs SIGKILL, la nuance qui compte : SIGTERM est une demande — le processus peut fermer ses connexions, flusher ses buffers, sauvegarder, puis sortir. SIGKILL ne lui parvient jamais : le noyau le supprime, sans aucun cleanup. C’est le protocole exact de docker stop : SIGTERM au PID 1 du conteneur, 10 secondes de grâce, puis SIGKILL. Une app qui n’écoute pas SIGTERM (ou lancée derrière un shell qui ne relaie pas les signaux) meurt brutalement à chaque déploiement.
stdin, stdout, stderr et redirections
Chaque processus démarre avec trois flux numérotés : l’entrée standard (0), la sortie standard (1) et la sortie d’erreur (2). Le shell peut les rebrancher où il veut :
stdin (0) stdout (1)
clavier ─────────▶ processus ─────────▶ terminal
│
└─── stderr (2) ─────▶ terminal
cmd > out.log stdout → fichier (écrase ; >> ajoute)
cmd 2> err.log stderr → fichier
cmd > f 2>&1 les deux → f (l'ordre compte !)
cmd1 | cmd2 stdout de cmd1 → stdin de cmd2
Le pipe est la pièce maîtresse : il branche la sortie d’un programme sur l’entrée du suivant, sans fichier intermédiaire. Un cas réel — trouver les IP qui martèlent votre endpoint de login :
grep "POST /api/login" access.log \
| awk '{print $1}' # extraire la 1re colonne : l'IP
| sort # uniq exige des lignes adjacentes
| uniq -c # compter les occurrences par IP
| sort -rn # tri numérique décroissant
| head -10 # top 10 des IP les plus insistantes
💡 Réflexe à montrer — le
sortavantuniq -cn’est pas décoratif :uniqne fusionne que les lignes adjacentes. L’oublier donne des comptes faux — le genre de détail qui prouve en entretien que vous avez vraiment pratiqué.
Concepts clés à maîtriser
- Permissions rwx — trois triplets : propriétaire, groupe, autres. En octal : r=4, w=2, x=1.
chmod 755=rwxr-xr-x(exécutable par tous, modifiable par le seul propriétaire) ;600=rw-------(clé SSH privée).sudoexécute une commande en root — un privilège à justifier, pas un réflexe. - Variables d’environnement & PATH — un ensemble clé=valeur hérité par les processus enfants (
export API_URL=…). LePATHliste les répertoires où le shell cherche les commandes, dans l’ordre — c’est pourquoi un script local se lance avec./script.sh, et pourquoiwhich pythonlève les doutes. - systemd en survol — le gestionnaire de services :
systemctl status nginx(état),start/stop/restart,enable(démarrage au boot). Les logs passent parjournalctl -u nginx -f(le-fsuit en direct). - Les commandes qui sauvent —
grep -rn "motif" .(chercher dans le code),find . -name "*.log"(trouver des fichiers),ps aux(processus en cours),ss -tlnp(ports en écoute et par qui),tail -f app.log(suivre un log en direct),df -h(espace disque),du -sh *(qui prend la place),top/htop(CPU/RAM en temps réel). - SSH & clés — une paire clé publique/privée remplace le mot de passe : la publique va dans
~/.ssh/authorized_keysdu serveur, la privée ne quitte jamais votre machine. Plus sûr (rien à deviner par force brute) et scriptable (CI, déploiements).
🎤 En entretien — « un serveur ne répond plus, tu fais quoi ? » Déroulez une méthode, pas une liste : (1) j’accède — ping, puis SSH ; (2)
top— CPU saturé ? plus de RAM ? un processus fou ? ; (3)df -h— disque plein, la cause la plus bête et la plus fréquente ; (4)ss -tlnp— mon service écoute-t-il encore son port ? ; (5)systemctl status apppuisjournalctl -u app -n 100outail -fsur ses logs — l’erreur y est presque toujours. Une démarche structurée vaut dix commandes récitées.
En entretien
« SIGTERM vs SIGKILL ? » — SIGTERM (15) demande un arrêt propre : le processus peut l’intercepter pour fermer connexions et buffers. SIGKILL (9) est ininterceptable : le noyau tue sans cleanup. Bonus : docker stop envoie SIGTERM, attend 10 s, puis SIGKILL — d’où l’importance de gérer SIGTERM dans une app conteneurisée.
« Que signifie chmod 640 ? » — Octal : 6 = rw- (propriétaire), 4 = r— (groupe), 0 = --- (autres). Lecture-écriture pour le propriétaire, lecture seule pour le groupe, rien pour le reste du monde — typique d’un fichier de config avec secrets.
« Comment un processus est-il créé sous Linux ? » — Par fork() : le parent se clone (même code, mémoire copiée) ; puis en général exec() remplace l’image du clone par le nouveau programme. Le shell fait fork + exec pour chaque commande, et wait() pour récupérer le code de sortie.
« À quoi sert le PATH ? » — C’est la liste ordonnée des répertoires où le shell cherche un exécutable quand on tape une commande sans chemin. Premier trouvé, premier servi — d’où les surprises quand deux versions d’un outil cohabitent (which pour trancher).
« Comment lire les logs d’un service en production ? » — Service systemd : journalctl -u nom-du-service -f (ou -n 200 pour les 200 dernières lignes). Fichier classique : tail -f /var/log/app.log, filtré avec grep. Conteneur : docker logs -f, puisque l’app logge sur stdout/stderr.
Pièges & idées reçues
⚠️ Les deux réflexes toxiques —
kill -9d’entrée de jeu : le processus meurt sans flusher ni libérer ses ressources (fichiers de lock orphelins, données corrompues) ; toujours SIGTERM d’abord, SIGKILL en dernier recours. Etchmod 777« pour que ça marche » : vous venez de donner l’écriture à tous les utilisateurs du système — corrigez le propriétaire (chown) ou le groupe, pas les permissions du monde entier.
- « df dit que le disque est plein, mais du ne trouve rien » — un processus tient ouvert un fichier supprimé : l’espace n’est libéré qu’à la fermeture.
lsof | grep deleted, puis redémarrer le service fautif. Classique avec les gros logs supprimés à chaud. - Une variable non exportée n’existe pas pour les enfants —
VAR=xreste locale au shell ; il fautexport VAR=xpour qu’un processus lancé ensuite la voie. Source fréquente de « ça marche dans mon terminal, pas dans le service ». sudon’est pas un mot magique — relancer une commande échouée avecsudosans comprendre pourquoi elle échouait crée des fichiers appartenant à root dans votre projet, et le vrai problème reste entier.netstatest déprécié — l’outil moderne estss(même usage :ss -tlnp), présent partout oùnetstata disparu des images minimales.
Pour aller plus loin
- MIT — The Missing Semester : le cours que toutes les écoles devraient donner (shell, outils, debugging)
- explainshell.com : colle une commande, chaque flag est expliqué depuis les man pages
- man7.org : les man pages de référence (signal(7), proc(5)…)
- Julia Evans — Wizard Zines : les fanzines qui rendent
strace, les signaux et les pipes limpides - Pratiquer : ouvrir un shell et explorer
ls /proc/$$/— le répertoire du processus… de votre propre shell
The essentials
Your servers run Linux. So do your Docker containers. Your CI, your Raspberry Pi, and 100% of the top 500 supercomputers. A developer who can find their way around a Linux shell debugs alone what others escalate — exactly what a recruiter looks for in an intern.
Two founding ideas structure the whole system:
- Everything is a file — disks (
/dev/sda), sockets, and even kernel state:/procis a virtual filesystem where every process has its directory (/proc/1234/), wherecat /proc/cpuinforeads the CPUs and/proc/meminfothe memory. Read, write, redirect: one interface for everything. - Small composable tools — the Unix philosophy: each program does one thing well, text is the universal interface, and the pipe
|assembles them into powerful chains.grepcan’t sort,sortcan’t filter — together, they do log analysis.
How it works
Processes: fork, exec, signals
A new process is always born through fork() (the parent clones itself) usually followed by exec() (the clone replaces itself with the new program) — that’s how your shell launches every command. Each process has a PID; the very first, PID 1 (systemd), boots the system and adopts orphans.
You talk to processes through signals:
| Signal | # | Effect | Catchable? |
|---|---|---|---|
| SIGHUP | 1 | terminal closed / reload config | yes |
| SIGINT | 2 | Ctrl+C | yes |
| SIGTERM | 15 | “terminate cleanly” (default of kill) | yes |
| SIGKILL | 9 | immediate death, decided by the kernel | no |
| SIGSEGV | 11 | invalid memory access | yes |
| SIGSTOP / SIGCONT | 19 / 18 | pause / resume | no / yes |
SIGTERM vs SIGKILL, the nuance that matters: SIGTERM is a request — the process can close its connections, flush its buffers, save, then exit. SIGKILL never reaches it: the kernel removes it, with zero cleanup. That’s the exact protocol of docker stop: SIGTERM to the container’s PID 1, a 10-second grace period, then SIGKILL. An app that doesn’t listen for SIGTERM (or launched behind a shell that doesn’t forward signals) dies brutally on every deployment.
stdin, stdout, stderr and redirections
Every process starts with three numbered streams: standard input (0), standard output (1) and standard error (2). The shell can rewire them at will:
stdin (0) stdout (1)
keyboard ─────────▶ process ─────────▶ terminal
│
└─── stderr (2) ─────▶ terminal
cmd > out.log stdout → file (overwrites; >> appends)
cmd 2> err.log stderr → file
cmd > f 2>&1 both → f (order matters!)
cmd1 | cmd2 stdout of cmd1 → stdin of cmd2
The pipe is the centerpiece: it plugs one program’s output into the next one’s input, no intermediate file. A real case — find the IPs hammering your login endpoint:
grep "POST /api/login" access.log \
| awk '{print $1}' # extract the 1st column: the IP
| sort # uniq requires adjacent lines
| uniq -c # count occurrences per IP
| sort -rn # descending numeric sort
| head -10 # top 10 most insistent IPs
💡 Reflex to show — the
sortbeforeuniq -cisn’t decorative:uniqonly merges adjacent lines. Forgetting it produces wrong counts — the kind of detail that proves in an interview you’ve actually practiced.
Key concepts to master
- rwx permissions — three triplets: owner, group, others. In octal: r=4, w=2, x=1.
chmod 755=rwxr-xr-x(executable by everyone, writable only by the owner);600=rw-------(private SSH key).sudoruns a command as root — a privilege to justify, not a reflex. - Environment variables & PATH — a key=value set inherited by child processes (
export API_URL=…).PATHlists the directories where the shell looks for commands, in order — that’s why a local script runs with./script.sh, and whywhich pythonclears up doubts. - systemd at a glance — the service manager:
systemctl status nginx(state),start/stop/restart,enable(start at boot). Logs go throughjournalctl -u nginx -f(-ffollows live). - The commands that save the day —
grep -rn "pattern" .(search the code),find . -name "*.log"(find files),ps aux(running processes),ss -tlnp(listening ports and by whom),tail -f app.log(follow a log live),df -h(disk space),du -sh *(what takes the space),top/htop(CPU/RAM in real time). - SSH & keys — a public/private key pair replaces the password: the public key goes into the server’s
~/.ssh/authorized_keys, the private one never leaves your machine. Safer (nothing to brute-force) and scriptable (CI, deployments).
🎤 In an interview — “a server stopped responding, what do you do?” Unroll a method, not a list: (1) I get access — ping, then SSH; (2)
top— CPU maxed out? out of RAM? a runaway process?; (3)df -h— full disk, the dumbest and most frequent cause; (4)ss -tlnp— is my service still listening on its port?; (5)systemctl status appthenjournalctl -u app -n 100ortail -fon its logs — the error is almost always there. A structured approach beats ten recited commands.
In an interview
“SIGTERM vs SIGKILL?” — SIGTERM (15) requests a clean shutdown: the process can catch it to close connections and flush buffers. SIGKILL (9) is uncatchable: the kernel kills without cleanup. Bonus: docker stop sends SIGTERM, waits 10 s, then SIGKILL — hence the importance of handling SIGTERM in a containerized app.
“What does chmod 640 mean?” — Octal: 6 = rw- (owner), 4 = r— (group), 0 = --- (others). Read-write for the owner, read-only for the group, nothing for the rest of the world — typical for a config file holding secrets.
“How is a process created on Linux?” — Through fork(): the parent clones itself (same code, copied memory); then usually exec() replaces the clone’s image with the new program. The shell does fork + exec for every command, and wait() to collect the exit code.
“What is PATH for?” — It’s the ordered list of directories where the shell looks for an executable when you type a command without a path. First found, first served — hence the surprises when two versions of a tool coexist (which settles it).
“How do you read a service’s logs in production?” — systemd service: journalctl -u service-name -f (or -n 200 for the last 200 lines). Classic file: tail -f /var/log/app.log, filtered with grep. Container: docker logs -f, since the app logs to stdout/stderr.
Pitfalls & misconceptions
⚠️ The two toxic reflexes —
kill -9as a first move: the process dies without flushing or releasing its resources (orphaned lock files, corrupted data); always SIGTERM first, SIGKILL as a last resort. Andchmod 777“to make it work”: you’ve just granted write access to every user on the system — fix the owner (chown) or the group, not the whole world’s permissions.
- “df says the disk is full, but du finds nothing” — a process is holding a deleted file open: the space is only freed on close.
lsof | grep deleted, then restart the guilty service. Classic with big logs deleted while hot. - A non-exported variable doesn’t exist for children —
VAR=xstays local to the shell; you needexport VAR=xfor a process launched afterwards to see it. Frequent source of “works in my terminal, not in the service”. sudois not a magic word — rerunning a failed command withsudowithout understanding why it failed creates root-owned files in your project, and the real problem remains untouched.netstatis deprecated — the modern tool isss(same usage:ss -tlnp), present everywherenetstathas vanished from minimal images.
Going further
- MIT — The Missing Semester: the course every school should teach (shell, tooling, debugging)
- explainshell.com: paste a command, every flag explained from the man pages
- man7.org: the reference man pages (signal(7), proc(5)…)
- Julia Evans — Wizard Zines: the zines that make
strace, signals and pipes crystal clear - Practice: open a shell and explore
ls /proc/$$/— the process directory… of your own shell