Les jobs cron, scripts de backup et commandes shell ponctuelles loguent typiquement dans un fichier plat ou dans /dev/null, ni l’un ni l’autre n’étant découvrable quand un incident arrive. systemd-cat est le petit utilitaire qui prend stdin (ou exécute une commande) et écrit les lignes dans le journal systemd avec un identifiant et une priorité choisis. Le résultat : un script qui apparaît dans journalctl -t my-backup -p err à côté de tout le reste, avec des champs structurés qu’une requête peut filtrer. Cet article est le guide pratique pour bien l’utiliser.
Comment vérifier
Après avoir câblé systemd-cat dans un script, le journal doit tenir la sortie avec l’identifiant et la priorité fixés.
echo "test from $(whoami) at $(date)" | systemd-cat -t test-cat -p info
journalctl -t test-cat --since "1 min ago" -o json-pretty | head -30
# Cherchez SYSLOG_IDENTIFIER et PRIORITY dans la sortie
# Streamer plusieurs lignes d'une commande longue
( echo "starting"; sleep 1; echo "midway"; sleep 1; echo "done" ) | \
systemd-cat -t demo-stream -p notice
journalctl -t demo-stream --since "1 min ago"
Erreur fréquente de vérification : piper dans systemd-cat fonctionne quand c’est l’opérateur qui lance, puis échoue silencieusement depuis cron parce que l’environnement de cron n’a pas XDG_RUNTIME_DIR et systemd-cat ne peut pas atteindre le journal utilisateur — voir étape 3.
Ce qui se passe vraiment
systemd-cat est un mince wrapper autour de sd_journal_send (l’API C libsystemd pour les écritures structurées dans le journal). Il s’utilise dans deux modes :
- Mode pipe —
commande | systemd-cat -t TAG -p PRIORITÉ. Lit stdin ligne par ligne, écrit chaque ligne comme une entrée de journal avec le tag donné (=SYSLOG_IDENTIFIER) et la priorité. - Mode exec —
systemd-cat -t TAG -p PRIORITÉ -- commande args. Exécute la commande elle-même, capture stdout et stderr et écrit les deux dans le journal. Stderr est écrit à la priorité fixée ; stdout utilise--stderr-prioritysi spécifié séparément. Le code de sortie de la commande est préservé.
Les priorités suivent syslog : emerg, alert, crit, err, warning, notice, info, debug. Un wrapper à notice avec stderr-priority err est un pattern courant — les lignes informationnelles restent sous le seuil de bruit, les vraies erreurs remontent en -p err.
La procédure
-
Utiliser le mode exec pour les jobs cron et les backups. C’est le pattern le plus propre — une ligne dans cron, toute la sortie dans le journal.
# /etc/cron.d/nightly-backup 0 2 * * * root systemd-cat -t nightly-backup -p notice --stderr-priority=err \ /usr/local/bin/backup-postgresDans le journal : chaque ligne du script de backup apparaît taguée
nightly-backup, avec les lignes informationnelles en notice et tout stderr en err.journalctl -t nightly-backup -p err --since todayest alors la ligne de triage. -
Utiliser le mode pipe pour les scripts qu’on ne veut pas wrapper entièrement. Utile dans les pipelines shell et quand seule une partie de la sortie compte.
#!/usr/bin/env bash set -euo pipefail exec 1> >(systemd-cat -t my-script -p info) exec 2> >(systemd-cat -t my-script -p err) echo "démarrage du travail" do_something_dangerous echo "terminé"Les deux lignes
execredirigent le stdout restant du script verssystemd-caten info, stderr en err. Tout ce qui vient après tombe dans le journal automatiquement. -
Dans cron, s’assurer que le répertoire runtime de l’utilisateur est disponible. C’est le piège qui mord les gens une fois et qui n’est plus jamais oublié.
-
Pour le cron root,
/run/systemd/journal/dev-logest toujours disponible — aucun correctif nécessaire. -
Pour le cron utilisateur (
crontab -een utilisateur normal), si vous voyezFailed to connect to system bus, mettezXDG_RUNTIME_DIRdans le crontab :XDG_RUNTIME_DIR=/run/user/1000 0 2 * * * systemd-cat -t my-job -p notice -- /home/me/bin/the-job -
Ou, mieux, lancez ça comme un timer systemd utilisateur — l’environnement du timer est correct par construction. Voir systemd-timers-vs-cron.
-
-
Ajouter des champs structurés pour ce qu’on voudra interroger plus tard.
systemd-catlui-même n’expose pas ça, mais la commandeloggersous-jacente oui.logger --journald=- <<EOF MESSAGE=backup terminé SYSLOG_IDENTIFIER=nightly-backup PRIORITY=5 BACKUP_JOB=postgres-main BACKUP_BYTES=8543219200 BACKUP_DURATION_MS=49210 EOF # Puis interrogeable comme : journalctl BACKUP_JOB=postgres-main --since "1 day ago" -o json-prettyPRIORITY=5est notice. Les noms de champs personnalisés sont par convention en majuscules. Ce pattern est la façon de faire émettre par des scripts des données qui s’intègrent proprement avec le filtrage journalctl décrit dans journalctl-filtering-deep. -
Utiliser
--identifierpar job logique, pas par hôte. Des identifiants commenightly-backup,cert-renewal,disk-rotationrendentjournalctl -t <nom>instantanément utile. Un identifiant fourre-tout commecron-jobsdéfait l’objectif. -
Combinez avec
--service-type=notify-reloadpour les scripts à longue durée. Si un script doit tourner pendant des heures, le wrapper dans une unité systemd transitoire (systemd-run --unit=my-job.service --collect) donne la sortie au journal, des limites de ressources et unsystemctl status my-jobqui montre l’état courant — mieux quesystemd-catpour tout ce qui dépasse un one-shot.
Notes opérationnelles
- Le rate limiter du journal (
RateLimitIntervalSec/RateLimitBurstdans/etc/systemd/journald.conf) jette les messages d’un script bruyant sans erreur ; ajustez la limite par service via un drop-in si un burst légitime est attendu. systemd-cat -paccepte des priorités numériques (0–7) et nommées — les deux fonctionnent, mais utilisez les noms dans les scripts pour la lisibilité.- Le tag
-tn’est pas la même chose qu’une unité systemd ;journalctl -uetjournalctl -tfiltrent sur des champs différents. La plupart des scripts veulent-t. logger(la commande syslog BSD-style) écrit aussi dans le journal, mais ne donne pas de champs structurés sauf à utiliser le mode--journald.- Pour des taux d’écriture très élevés, préférez wrapper le script dans une unité systemd et utiliser le journal directement via stdout — le mode pipe de
systemd-catintroduit un petit surcoût par ligne.
Pour interroger ce que ces scripts émettent, voir journalctl-filtering-deep. Pour l’alternative timer systemd à cron, voir systemd-timers-vs-cron.
Stack Harbor câble systemd-cat (et logger --journald structuré) dans chaque script opérationnel livré dans le cadre de l’offre opérations infogérées — exécutions de backup, renouvellements de certificats, rotations de logs tombent tous dans le journal avec la même discipline de tag et de priorité, pour qu’un même filtre de triage fonctionne dans chaque environnement client.