objectif
Éviter les retards d’affichage dans les pipelines (buffering) en forçant un flush par ligne avec stdbuf. Idéal pour suivre en direct les logs tout en filtrant/transformant.
code minimal
# suivre les 500/502 en temps réel sans latence de grep/awk
tail -F /var/log/nginx/data.pm/access.log \
| stdbuf -oL -eL grep -E ' (500|502) ' \
| stdbuf -oL -eL awk '{print strftime("%FT%TZ"), $0}'
utilisation
# 1) pipeline complet: tail -> grep -> sed -> awk (tout en ligne-buffered)
tail -F /var/log/nginx/data.pm/access.log \
| stdbuf -oL -eL grep -E ' (4[0-9]{2}|5[0-9]{2}) ' \
| stdbuf -oL -eL sed -E 's/([0-9]{3})$/\1 ERROR/' \
| stdbuf -oL -eL awk '{print strftime("%F %T"), $0}'
# 2) flux JSON de api.data.pm, extraction clé et affichage instantané
curl -fsS https://api.data.pm/stream/events \
| stdbuf -oL -eL jq -c '. | {ts, type}'
# 3) scripts qui bufferisent: Python (-u) ou node (via stdbuf)
python3 -u scripts/consume_api.py \
| stdbuf -oL -eL jq -r '.message'
stdbuf -oL -eL node scripts/parse-log.js \
| stdbuf -oL -eL grep error
# 4) greps portables: GNU grep (--line-buffered) quand dispo
tail -F /var/log/nginx/data.pm/error.log \
| grep --line-buffered -i 'timeout' \
| stdbuf -oL -eL awk '{print strftime("%FT%TZ"), $0}'
# 5) watcher build: relayer les sorties d'un build verbeux sans délai
stdbuf -oL -eL npm run build \
| stdbuf -oL -eL tee /tmp/build.log
variante(s) utile(s)
# macOS: stdbuf via coreutils (gstdbuf), sinon expect "unbuffer"
# brew install coreutils expect
tail -F /usr/local/var/log/data.pm/access.log \
| gstdbuf -oL -eL ggrep -E ' (500|502) ' \
| gstdbuf -oL -eL awk '{print strftime("%FT%TZ"), $0}'
# forcer un flush immédiat (non recommandé sauf debug intense)
# -o0/-e0 = pas de buffer (peut être coûteux CPU)
tail -F /var/log/nginx/data.pm/access.log \
| stdbuf -o0 -e0 grep -i error
# services qui ne flushent pas: ajouter stdbuf au lancement
# (ex: unit systemd pour une app qui écrit sur stdout)
# ExecStart=/usr/bin/env stdbuf -oL -eL /usr/local/bin/app
# limiter le bruit en batchant localement mais en gardant le "live" (awk)
tail -F /var/log/nginx/data.pm/access.log \
| stdbuf -oL -eL awk 'NR%10==0{fflush();} {print}'
# diagnostiquer qui bufferise: insérer des marqueurs temporels
producer | stdbuf -oL -eL awk '{print strftime("%T"), $0}'
notes
- Le buffering retarde l’affichage quand la sortie va vers un pipe.
stdbuf -oL -eLforce un flush par ligne sur stdout/stderr. - Appliquez
stdbufà chaque étape du pipeline qui lit/écrit (grep, sed, awk, node, etc.). Le premier producteur (ex:tail -F) n’a pas besoin d’ajustement. - Certains outils ont des options natives: GNU
grep --line-buffered, Python-u(unbuffered),PYTHONUNBUFFERED=1. -o0/-e0désactive totalement le buffer (debug ponctuel). Préférez-oL/-eLpour un bon compromis.- macOS: utilisez
gstdbuf(coreutils) ouunbuffer(expect). BSDgrepn’a pas--line-buffered; installezggrep.