Bash - Afficher sur la console et dans un fichier de log en même temps
Fatigué des scripts Bash silencieux ? Découvrez la méthode simple et efficace pour afficher la sortie d'une commande sur la console tout en l'écrivant ligne par ligne dans un fichier de log.
Traduction automatique
Cet article a plus d'un an, mais il a été relu le 30 juillet 2026 — son contenu est toujours exact.
Cet article fait partie de la série Écrire de meilleurs scripts Bash :
- Bash - ASCII art
- Bash - Charger des variables d'environnement depuis un fichier
- Bash - Script pour ajouter des fonctionnalités de log à votre script
- Bash - Afficher sur la console et dans un fichier de log en même temps
- Linux - Comparer deux versions du même script
- Linux - Trier les fonctions dans un script Bash
- Linux - Générer de la documentation à partir de scripts Bash
- Linux - Tirez parti du nombre de CPU dont vous disposez ; lancez des jobs concurrents
- Linux - Utiliser une barre de progression dans vos scripts
- Linux - Scripts Bash - Lancer des tests unitaires avec bats/bats

Cet article montre comment faire en sorte qu'une commande Bash de longue durée écrive à la fois sur la console et dans un fichier de log (au lieu de l'un ou l'autre seulement), en utilisant eval pour lancer la commande et en affichant chaque ligne à l'écran tout en l'ajoutant au fichier de log en temps réel — plutôt que de tout mettre en mémoire tampon pour l'afficher à la fin.
Dans mon article précédent Bash - Script pour ajouter des fonctionnalités de log à votre script, j'ai partagé une façon d'écrire des informations dans un fichier de log.
En lançant ls -alh /tmp, vous obtenez la liste de tous les fichiers du dossier /tmp et elle s'affiche sur votre console. En lançant ls -alh /tmp >> application.log, vous ne verrez pas la liste dans votre console puisque tout sera écrit dans le fichier application.log.
Comment afficher la sortie d'une commande comme ls par exemple à la fois sur la console et dans un fichier de log ?
Résultat
Les mêmes lignes, deux fois : une fois affichées en direct sur la console, une fois ajoutées à /tmp/test.log — la preuve que les deux sorties se produisent vraiment en même temps, et non l'une après l'autre.
Pour l'illustration ci-dessus, le script a listé un petit dossier de démo au lieu de /tmp pour des raisons de lisibilité ; en pratique, vous le pointerez vers la commande de longue durée que vous voulez tracer.
Pourquoi ça fonctionne
La commande passe par eval, et sa sortie est redirigée vers une boucle while read. Pour chaque ligne qui en sort, la boucle fait deux choses immédiatement, avant de lire la ligne suivante : elle l'affiche avec echo sur la console, puis elle l'ajoute au fichier de log. Rien n'est mis en mémoire tampon pour être vidé à la fin — c'est ce qui garde les deux sorties synchronisées.
Par exemple, récupérons la liste de tous les fichiers sous /tmp, et ce de manière récursive. Pour cela, notre commande sera ls -alhR /tmp.
Cette commande va probablement prendre du temps et c'est justement l'objectif : lancer une commande longue et s'assurer que l'utilisateur verra la sortie à l'écran, pour qu'il sache que le script fait quelque chose, tout en redirigeant aussi la sortie vers un fichier de log pour une analyse ultérieure en cas de problème (ou simplement parce que le script est lancé dans un cron).
Si « le script fait quelque chose » est tout ce que votre utilisateur a besoin de savoir, une barre de progression est souvent plus agréable qu'un mur de texte qui défile.
#!/usr/bin/env bashset -euo pipefail
declare -r command="ls -alhR /tmp"
declare -r LOGFILE="/tmp/test.log"touch "${LOGFILE}"
function log::write() { printf '[%s] %s%s\n' "$(date +"%Y-%m-%dT%H:%M:%S%z")" "${line}" >>"${LOGFILE}" return 0}
eval "${command}" | while IFS= read -r line; do echo "${line}" # Output on the console (stdout) log::write "${line}" # And append in the log file doneCe script exécute une commande ls et traite sa sortie ligne par ligne : chaque ligne est affichée à la console et enregistrée dans un fichier journal avec un horodatage.
La partie principale est la fonction eval.
La commande (ls -alhR /tmp) sera lancée et, pour chaque ligne, nous ferons un echo de la ligne à l'écran et la redirigerons aussi dans un fichier texte.
L'exemple ci-dessous fait presque la même chose, c'est-à-dire qu'il exécute une commande et l'affiche à la fois dans un fichier et sur la console mais... comme vous le voyez, la commande est lancée et tout est redirigé vers le fichier. Donc, pendant plusieurs secondes, l'utilisateur n'a aucune sortie à l'écran et peut penser que le script est bloqué. Ensuite, une fois la commande terminée avec succès, et seulement alors, le fichier de log est affiché, d'un bloc, sur la console.
#!/usr/bin/env bashset -euo pipefail
declare -r command="ls -alhR /tmp"declare -r LOGFILE="/tmp/test.log"
eval "${command}" > "${LOGFILE}"cat "${LOGFILE}"Ce script exécute la commande ls -alhR /tmp pour lister tous les fichiers du répertoire /tmp de manière récursive, redirige le résultat dans un fichier journal, puis affiche le contenu de ce fichier. Les variables sont déclarées comme constantes en lecture seule pour éviter les modifications accidentelles.
Ne faites pas ce genre de choses !
Cet article fait partie de la série Écrire de meilleurs scripts Bash :
- Bash - ASCII art
- Bash - Charger des variables d'environnement depuis un fichier
- Bash - Script pour ajouter des fonctionnalités de log à votre script
- Bash - Afficher sur la console et dans un fichier de log en même temps
- Linux - Comparer deux versions du même script
- Linux - Trier les fonctions dans un script Bash
- Linux - Générer de la documentation à partir de scripts Bash
- Linux - Tirez parti du nombre de CPU dont vous disposez ; lancez des jobs concurrents
- Linux - Utiliser une barre de progression dans vos scripts
- Linux - Scripts Bash - Lancer des tests unitaires avec bats/bats





