Tu connais les pipes | du shell ? Ils sont parfaits mais temporaires : les données transitent et disparaissent. Un canal nommé (aussi appelé FIFO pour First In, First Out) est un fichier spécial qui persiste. Tu peux y écrire depuis un terminal et lire depuis un autre, comme un vrai tuyau de communication entre processus.
Un canal nommé (named pipe ou FIFO) est un fichier spécial de type p. Contrairement à un pipe anonyme (|) qui n'existe que pendant l'exécution d'un processus, le FIFO existe dans le système de fichiers et peut être utilisé par n'importe quel processus, à n'importe quel moment.
# Créer un canal nommé
mkfifo mondossier/mon-fifo
# Vérifier son type
ls -la mondossier/mon-fifo
# Résultat : prw-r--r-- 1 david david 0 ... mon-fifo
# ^
# |_ Le 'p' indique que c'est un pipe (FIFO)| Caractéristique | Canal nommé (FIFO) | Fichier classique | Pipe anonyme | |
|---|---|---|---|
| Persistant après exécution | Oui (jusqu'à suppression) | Oui | Non |
| Communication inter-processus | Oui | Oui (via fichier) | Oui (entre deux processus) |
| Plusieurs lecteurs simultanés | Oui | Oui | Oui |
| Plusieurs écrivains simultanés | Oui | Oui | Oui |
| Utilise le disque | Non (en mémoire) | Oui | Non |
| Accessible par nom | Oui | Oui | Non (anonyme) |
# Syntaxe simple
mkfifo /tmp/mon-fifo
# Créer dans ton dossier personnel
mkfifo ~/mon-fifo
# Vérifier la création
file ~/mon-fifo
# Affiche : /home/david/mon-fifo: fifo (named pipe)# Écrire du texte dans le FIFO
echo "Bonjour depuis le terminal" > ~/mon-fifo
# Écrire plusieurs lignes
printf "Ligne 1\nLigne 2\nLigne 3\n" > ~/mon-fifo
# Écrire depuis un fichier
cat fichier.txt > ~/mon-fifo# Lire le contenu (bloque jusqu'à données disponibles)
cat ~/mon-fifo
# Lire ligne par ligne avec read
while IFS= read -r ligne; do
echo "Reçu : $ligne"
done < ~/mon-fifoOuvre deux terminaux. Dans le premier :
# Terminal 1 : créer le FIFO et lire
mkfifo ~/chat-fifo
cat ~/chat-fifoDans le second :
# Terminal 2 : écrire dans le FIFO
echo "Salut, ça fonctionne !" > ~/chat-fifoLe message apparaît dans le terminal 1. Chaque nouveau message envoyé depuis le terminal 2 sera affiché dans le terminal 1.
# Créer un FIFO comme fichier de log central
mkfifo /tmp/log-central
# Terminal 1 : tous les logs arrivent ici
cat /tmp/log-central > ~/application.log &
# Terminal 2 : plusieurs programmes écrivent dedans
echo "$(date) : Service démarré" > /tmp/log-central
echo "$(date) : Utilisateur connecté" > /tmp/log-central
nginx -g 'daemon off;' > /tmp/log-central 2>&1 &
mysqld --log=/tmp/log-central &# Créer un FIFO pour capturer les logs
mkfifo ~/debug-pipe
# Terminal 1 : surveiller les logs en direct
tail -f ~/debug-pipe &
# Terminal 2 : ta commande génère des logs
./mon-script.sh > ~/debug-pipe 2>&1# script-parent.sh
#!/bin/bash
mkfifo /tmp/pipe-parent
# Démarrer l'enfant en arrière-plan
bash script-enfant.sh &
# Envoyer des commandes
echo "START" > /tmp/pipe-parent
sleep 5
echo "STOP" > /tmp/pipe-parent
sleep 1
echo "QUIT" > /tmp/pipe-parent
# Nettoyer
rm -f /tmp/pipe-parent# script-enfant.sh
#!/bin/bash
while true; do
IFS= read -r cmd < /tmp/pipe-parent
case "$cmd" in
START) echo "Enfant : démarrage..." ;;
STOP) echo "Enfant : arrêt..." ;;
QUIT) echo "Enfant : au revoir !"; exit 0 ;;
esac
done# Serveur : lit les commandes depuis le FIFO
mkfifo /tmp/serveur-fifo
while IFS= read -r cmd < /tmp/serveur-fifo; do
echo "Commande reçue : $cmd"
# Exécuter la commande
eval "$cmd"
done > /tmp/serveur-output 2>&1 &# Client : envoyer des commandes
echo "ls -la /home" > /tmp/serveur-fifo
echo "df -h" > /tmp/serveur-fifo
# Lire les résultats
cat /tmp/serveur-output# Si un programme ne peut qu'écrire dans un fichier, utiliser un FIFO
mkfifo /tmp/audio-stream
cat /tmp/audio-stream | ton-programme-audio &# Syntaxe de base
mkfifo /chemin/vers/fifo
# Avec permissions personnalisées
mkfifo -m 600 /tmp/fifo-prive
# Créer plusieurs
mkfifo ~/pipe1 ~/pipe2 ~/pipe3file ~/mon-fifo
# Affiche : /home/david/mon-fifo: fifo (named pipe)ls -la /tmp/*.fifo /tmp/*.pipe 2>/dev/null
# ou lister tout
ls -la | grep '^p'Les opérations de lecture et d'écriture sur un FIFO sont bloquantes par défaut. Cela signifie :
read bloque jusqu'à ce que des données soient disponibleswrite bloque jusqu'à ce que les données soient lues# Ouvrir le FIFO en mode non-bloquant
exec 3> /tmp/mon-fifo
echo "Texte" >&3# Utiliser timeout pour ne pas bloquer indéfiniment
timeout 5 cat /tmp/mon-fifo
# Affiche les données ou rien si timeoutSi tu veux qu'un processus lise et écrive sur le même FIFO, ouvre-le dans les deux directions :
# Processus bidirectionnel
mkfifo /tmp/fifo-bidir
# Ouvre une extrémité en lecture, l'autre en écriture
exec 3<>/tmp/fifo-bidir
# Écrire
echo "Question" >&3
# Lire la réponse
timeout 5 cat <&3rm ~/mon-fifo/tmp/serveur-cmds, /tmp/logs-app/tmp ou ton dossier personnel (pas dans /dev)timeout si ton lecteur doit mourir proprementwhile IFS= read -r ligne < "$FIFO" pour lire ligne par lignefile()) pour les gros volumes de données# Personne ne lit le FIFO, l'écriture bloque
echo "test" > ~/mon-fifo
# ^ bloque ici
# Solution : avoir un processus qui lit, ou utiliser non-bloquant
timeout 1 cat ~/mon-fifo &
sleep 0.5
echo "test" > ~/mon-fifo# Le FIFO est vide (les données ont déjà été lues)
# ou personne n'a encore écrit dedans
# Vérifier que l'écrivain a bien envoyé quelque chose
# Un lecteur précédent a tout consommé
# Recommencer :
# Terminal 1 : cat ~/mon-fifo (lance le lecteur)
# Terminal 2 : echo "msg" > ~/mon-fifo (envoie après)# Les FIFO sont en mémoire, pas sur disque
# Solution : créer le FIFO au démarrage du script
if [ ! -p ~/mon-fifo ]; then
mkfifo ~/mon-fifo
fi# Si plusieurs programmes écrivent simultanément
# Les lignes peuvent se mélanger
# Solution : utiliser un lock ou unbuffering
{ flock -n 3 || true; echo "msg"; } > ~/mon-fifo| Commande | Usage |
|---|---|
mkfifo /chemin/fifo | Créer un canal nommé (FIFO) |
file /chemin/fifo | Vérifier que c'est bien un FIFO |
ls -la | grep '^p' | Lister tous les FIFO du répertoire |
echo "msg" > ~/fifo | Écrire dans un FIFO |
cat ~/fifo | Lire depuis un FIFO |
rm ~/fifo | Supprimer un FIFO |
timeout N cat ~/fifo | Lecture avec timeout (non-bloquante) |
Les canaux nommés sont un outil puissant pour la communication inter-processus sur Linux. Ils permettent de créer des architectures simples sans réseau ni configuration avancée. Maîtrise-les et tu disposeras d'un outil supplémentaire pour structurer tes scripts et automatisations.