Ma Publicité

Soutenez la Création

Aidez-moi à partager du contenu exclusif.

Soutenir

Comments

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde

Logs illisibles : pipeline journalctl + jq qui sauve

Logs illisibles : pipeline journalctl + jq qui sauve

Il y a des jours où tu ouvres un log système, tu fais défiler trois secondes, et tu sens déjà ton cerveau partir en fumée.

Des lignes à rallonge. Des timestamps partout. Des champs que tu n’as jamais demandés. Et au milieu, ton vrai problème, planqué comme une aiguille dans une botte de JSON.

Moi, ça m’arrive souvent quand je bosse sur un serveur Linux un peu vivant (un reverse proxy, un service systemd maison, un conteneur, un agent de monitoring, etc.). Et c’est exactement là que ce pipeline m’a sauvé plus d’une fois :

journalctl pour récupérer, filtrer, borner le temps.
jq pour rendre ça lisible, trier, extraire, colorer mentalement.

On va faire simple, pratique, et directement réutilisable.

Terminal avec logs systemd

Pourquoi journalctl est à la fois génial… et pénible

journalctl c’est super parce que :

  • tout est là (systemd, kernel, services, boots)
  • tu peux filtrer par service, par période, par priorité
  • tu peux exporter en JSON

Mais c’est pénible parce que, par défaut, tu lis des logs comme un humain en 1987. Et quand tu as des messages applicatifs au format JSON dans le champ MESSAGE, tu te retrouves avec du JSON dans une ligne, dans un autre format, avec l’habillage systemd autour. Donc double illisibilité.

L’idée ici, c’est de sortir proprement les événements en JSON depuis journald, puis de laisser jq faire le boulot.

Le premier réflexe : sortir du JSON exploitable

La base, c’est ça :

bash journalctl -u monservice -o json

Sauf que -o json sort un objet JSON par ligne, et jq adore ça. Donc on enchaîne :

bash journalctl -u monservice -o json | jq .

Bon. C’est déjà mieux.

Mais tu vas vite vouloir :

  • limiter à la session courante
  • borner une période
  • ne pas te taper 200 000 lignes
  • n’afficher que certains champs

On arrive au vrai pipeline.

Le pipeline « qui sauve » pour un service systemd

Celui que je retape tout le temps, en mode squelette :

bash journalctl -u monservice --since "1 hour ago" -o json
| jq -r '{ts: .__REALTIME_TIMESTAMP, lvl: .PRIORITY, msg: .MESSAGE}'

Ça donne un JSON réduit. Mais les timestamps journald sont en microsecondes depuis epoch, pas directement lisibles. Donc on va convertir.

Conversion du timestamp journald en date lisible

jq peut faire ça, mais on doit diviser par 1 000 000.

bash journalctl -u monservice --since "1 hour ago" -o json
| jq -r ' .__REALTIME_TIMESTAMP as $t | { time: ($t | tonumber / 1000000 | todateiso8601), host: ._HOSTNAME, unit: ._SYSTEMD_UNIT, pid: ._PID, prio: .PRIORITY, msg: .MESSAGE } '

Déjà là, tu as quelque chose de « humain ».

Astuce : afficher en format texte propre (et pas du JSON)

Parfois tu ne veux pas du JSON. Tu veux juste lire vite.

bash journalctl -u monservice --since "2 hours ago" -o json
| jq -r ' .__REALTIME_TIMESTAMP as $t | "($t|tonumber/1000000|todateiso8601) [prio:(.PRIORITY)] pid=(._PID) (.MESSAGE)" '

Là tu as une sortie lisible, prête à scroller.

Filtrer par niveau de logs (priorité)

journald encode PRIORITY de 0 à 7. En gros :

  • 0 à 3 : erreurs graves
  • 4 : warning
  • 5 : notice
  • 6 : info
  • 7 : debug

Filtrer sur les erreurs et warnings :

bash journalctl -u monservice --since "24 hours ago" -o json
| jq -r 'select(.PRIORITY|tonumber <= 4) | .MESSAGE'

Ça, c’est le genre de truc qui te fait gagner 20 minutes direct.

Quand le MESSAGE est lui-même du JSON

Cas très courant : ton appli logge un objet JSON dans MESSAGE.

Exemple, MESSAGE contient un truc du genre :

json {"level":"error","requestId":"abc","path":"/api","status":500,"err":"db timeout"}

Dans ce cas, tu peux parser le MESSAGE comme JSON dans jq.

bash journalctl -u monservice --since "1 hour ago" -o json
| jq -r ' .MESSAGE as $m | (try ($m|fromjson) catch null) as $mj | select($mj != null) | "($mj.level) ($mj.status) ($mj.path) requestId=($mj.requestId) ($mj.err)" '

Et là, magie. Tu lis enfin ce que ton app raconte, sans le bruit autour.

Exemple de JSON dans les logs

Repérer un pattern : grep, oui… mais mieux

Tu peux faire grep, mais autant rester dans jq quand tu es déjà en JSON.

Filtrer les messages qui contiennent « timeout » :

bash journalctl -u monservice --since "6 hours ago" -o json
| jq -r 'select(.MESSAGE|test("timeout"; "i")) | .MESSAGE'

Filtrer sur un champ JSON interne (si MESSAGE est JSON) :

bash journalctl -u monservice --since "6 hours ago" -o json
| jq -r ' .MESSAGE as $m | (try ($m|fromjson) catch null) as $mj | select($mj != null and ($mj.status|tostring) == "500") | $mj '

Oui, tu peux sortir l’objet entier. Et ensuite tu continues à filtrer.

Limiter le volume : tail et boots

Deux commandes que j’utilise en réflexe.

Derniers événements seulement

bash journalctl -u monservice -n 200 -o json | jq -r '.MESSAGE'

Depuis le dernier boot

bash journalctl -u monservice -b -o json | jq -r '.MESSAGE'

Et si tu veux lister les boots :

bash journalctl --list-boots

Puis :

bash journalctl -u monservice -b -1 -o json | jq -r '.MESSAGE'

Cas sysadmin réel : identifier un pic d’erreurs par minute

Tu as une avalanche d’erreurs, tu veux savoir quand ça a commencé, et si ça se calme.

On peut regrouper par minute.

bash journalctl -u monservice --since "2 hours ago" -o json
| jq -r ' select(.PRIORITY|tonumber <= 4) | (.__REALTIME_TIMESTAMP|tonumber/1000000) as $s | ($s - ($s % 60) | todateiso8601) '
| sort
| uniq -c
| sort -nr
| head

Ce n’est pas le pipeline le plus « beau », mais il est efficace. Tu obtiens un top des minutes les plus chargées en erreurs.

Bonus : extraire des champs journald utiles

Quelques champs pratiques que tu peux afficher sans te poser de questions :

  • ._SYSTEMD_UNIT : le service
  • ._COMM : nom de la commande
  • ._EXE : chemin binaire
  • ._PID : pid
  • ._UID : user id
  • ._GID : group id
  • ._HOSTNAME : hostname
  • .SYSLOG_IDENTIFIER : ident syslog si présent

Exemple :

bash journalctl -u monservice --since "1 day ago" -o json
| jq -r ' "(.SYSLOG_IDENTIFIER // "-") (. _SYSTEMD_UNIT // "-") pid=(._PID // "-") (.MESSAGE)" '

Petit détail : dans l’exemple ci dessus, je montre l’idée du fallback // "-". Selon les logs, certains champs peuvent être absents.

Mon « alias » perso (à copier)

Parce que oui, retaper ces options, c’est chiant.

Dans ~/.bashrc ou ~/.zshrc :

bash alias jql='journalctl -o json | jq -r'

Ensuite :

bash jql '"(.MESSAGE)"'

Ou pour un service :

bash journalctl -u monservice --since "30 min ago" -o json | jq -r '"(.MESSAGE)"'

Tu peux aussi faire un alias plus spécifique :

bash alias jerr='jq -r "select(.PRIORITY|tonumber<=4) | .MESSAGE"'

Et donc :

bash journalctl -u monservice --since "2 hours ago" -o json | jerr

Ça devient fluide. Et ça compte, surtout quand tu es en prod et que tu veux juste comprendre vite.

Petites erreurs classiques (et comment éviter de tourner en rond)

  1. Tu oublies -o json
    jq ne peut pas parser une sortie texte journald. Donc -o json quasi obligatoire ici.

  2. Tu as des logs tronqués
    Ajoute -l ou --full selon le besoin. Perso je fais souvent :

    bash journalctl -u monservice --since "1 hour ago" --no-pager --output=json --all

    Le --no-pager évite le scroll via less. Pratique dans des scripts.

  3. MESSAGE n’est pas toujours du JSON
    D’où le try ... catch dans jq. Sinon ton pipeline casse à la première ligne non JSON.

Conclusion rapide (et vraiment utilisable)

Si tu devais ne garder qu’un seul truc de cet article, garde ce réflexe :

  • journalctl en JSON
  • jq pour extraire ce que tu veux
  • et si ton MESSAGE est JSON, tu le parses avec fromjson

C’est littéralement ce qui transforme un mur de logs en quelque chose que tu peux lire, comprendre, et agir.

Si tu veux d’autres articles du même style, côté Linux, productivité et un peu business aussi quand même, passe faire un tour sur Le Blog Tech Pro de Samyn-Antoy ABASSE : Le Blog Tech Pro. J’y poste régulièrement des workflows concrets, pas des trucs théoriques qu’on oublie.

Serveur et monitoring

En parlant de trucs concrets, si tu cherches des commandes Linux qui sauvent, ou encore des [certifications Linux qui boostent](https://mon

Questions fréquemment posées

Pourquoi utiliser journalctl pour analyser les logs système sous Linux ?

Journalctl est un outil puissant car il centralise tous les logs (systemd, kernel, services, boots), permet de filtrer par service, période ou priorité, et offre une exportation en JSON, facilitant ainsi l'analyse des événements système.

Comment rendre les logs JSON de journalctl plus lisibles ?

En combinant journalctl avec jq : on récupère les logs au format JSON avec 'journalctl -o json' puis on utilise jq pour trier, extraire et colorer les informations importantes, ce qui améliore grandement la lisibilité.

Comment filtrer les logs d'un service systemd sur une période donnée ?

Utilisez le paramètre '--since' de journalctl, par exemple '--since "1 hour ago"' pour limiter les logs à la dernière heure. Ensuite, vous pouvez combiner cela avec jq pour extraire uniquement les champs souhaités.

Comment convertir le timestamp microseconde de journald en date lisible ?

Dans jq, divisez le champ __REALTIME_TIMESTAMP par 1 000 000 puis utilisez la fonction 'todateiso8601'. Par exemple : '. as $t | ($t|tonumber/1000000|todateiso8601)' permet d'obtenir une date au format ISO 8601 lisible.

Comment filtrer les logs par niveau de priorité avec journalctl et jq ?

Le champ PRIORITY varie de 0 à 7 (0-3 erreurs graves, 4 warning, etc.). Pour afficher seulement erreurs et warnings, filtrez avec jq comme ceci : 'select(.PRIORITY|tonumber <= 4)'. Cela réduit efficacement le volume des logs à analyser.

Que faire quand le champ MESSAGE contient lui-même un JSON ?

Avec jq, vous pouvez parser le contenu JSON du champ MESSAGE en utilisant 'fromjson'. Par exemple : '.MESSAGE as $m | (try ($m|fromjson) catch null) as $mj | select($mj != null)' permet d'extraire proprement les données imbriquées pour une analyse détaillée.

Enregistrer un commentaire

0 Commentaires

Comments

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde