web-dev-qa-db-fra.com

Comprendre la journalisation sous Linux

Si je comprends bien, le noyau Linux se connecte à /proc/kmsg fichier (principalement des messages liés au matériel) et /dev/log prise? N'importe où ailleurs? D'autres applications peuvent-elles également envoyer des messages à /proc/kmsg ou /dev/log? Dernier point mais non le moindre, ai-je raison de dire que c'est le démon syslog (rsyslog, syslog-ng) qui vérifie les messages de ces deux endroits et les distribue ensuite à divers fichiers comme /var/log/messages ou /var/log/kern.log ou même un serveur Syslog central?

68
Martin

Simplifié, ça se passe plus ou moins comme ceci:

Le noyau enregistre les messages (à l'aide de la fonction printk()) dans un tampon en anneau dans l'espace du noyau. Ces messages sont mis à la disposition des applications de l'espace utilisateur de deux manières: via le fichier /proc/kmsg (À condition que /proc Soit monté), et via l'appel système sys_syslog.

Il existe deux applications principales qui lisent (et, dans une certaine mesure, peuvent contrôler) le tampon en anneau du noyau: dmesg(1) et klogd(8). Le premier est destiné à être exécuté à la demande des utilisateurs, pour imprimer le contenu du tampon en anneau. Ce dernier est un démon qui lit les messages de /proc/kmsg (Ou appelle sys_syslog, Si /proc N'est pas monté) et les envoie à syslogd(8), ou à la console. Cela couvre le côté noyau.

Dans l'espace utilisateur, il y a syslogd(8). Il s'agit d'un démon qui écoute un certain nombre de sockets de domaine UNIX (principalement /dev/log, Mais d'autres peuvent également être configurés), et éventuellement le port UDP 514 pour les messages. Il reçoit également des messages de klogd(8) (syslogd(8) ne se soucie pas de /proc/kmsg). Il écrit ensuite ces messages dans certains fichiers dans /log, Ou dans des canaux nommés, ou les envoie à certains hôtes distants (via le protocole syslog, sur le port UDP 514), comme configuré dans /etc/syslog.conf.

Les applications de l'espace utilisateur utilisent normalement la fonction libcsyslog(3) pour enregistrer les messages. libc envoie ces messages au socket de domaine UNIX /dev/log (Où ils sont lus par syslogd(8)), mais si une application est chroot(2)- ed le les messages pourraient finir par être écrits sur d'autres sockets, fi à /var/named/dev/log. Il est bien sûr essentiel que les applications envoyant ces logs et syslogd(8) se mettent d'accord sur l'emplacement de ces sockets. Pour ces raisons, syslogd(8) peut être configurée pour écouter des sockets supplémentaires en plus du standard /dev/log.

Enfin, le protocole syslog n'est qu'un protocole de datagramme. Rien n'empêche une application d'envoyer des datagrammes Syslog à n'importe quel socket de domaine UNIX (à condition que ses informations d'identification lui permettent d'ouvrir le socket), en contournant complètement la fonction syslog(3) dans libc. Si les datagrammes sont correctement formatés, syslogd(8) peut les utiliser comme si les messages avaient été envoyés via syslog(3).

Bien sûr, ce qui précède ne couvre que la théorie de l'exploitation forestière "classique". D'autres démons (tels que rsyslog et syslog-ng, Comme vous le mentionnez) peuvent remplacer la simple syslogd(8), et faire toutes sortes de choses astucieuses, comme envoyer des messages à des hôtes distants via chiffré TCP, fournissent des horodatages haute résolution, etc.) et il y a aussi systemd, qui phagocyte lentement la partie UNIX de Linux. systemd a son propres mécanismes de journalisation, mais cette histoire devrait être racontée par quelqu'un d'autre. :)

Différences avec le monde * BSD:

Sur * BSD, il n'y a pas de klogd(8), et /proc N'existe pas (sur OpenBSD) ou est principalement obsolète (sur FreeBSD et NetBSD). syslogd(8) lit les messages du noyau à partir du périphérique de caractères /dev/klog et dmesg(1) utilise /dev/kmem pour décoder les noms du noyau. Seul OpenBSD a un /dev/log. FreeBSD utilise deux sockets de domaine UNIX /var/run/log Et var/rub/logpriv À la place, et NetBSD a un /var/run/log.

85
lcd047

L'autre réponse explique, comme le dit son auteur, la "journalisation classique" sous Linux. Ce n'est pas ainsi que les choses fonctionnent dans de nombreux systèmes de nos jours.

Le noyau

Les mécanismes du noyau ont changé.

Le noyau génère une sortie vers un tampon en mémoire. Les logiciels d'application peuvent y accéder de deux manières. Le sous-système de journalisation y accède généralement en tant que pseudo-FIFO nommé /proc/kmsg. Cette source d'informations de journal ne peut pas être utilement partagée entre les lecteurs de journal, car elle est lue une seule fois. Si plusieurs processus le partagent, ils n'obtiennent chacun qu'une partie du flux de données du journal du noyau. Il est également en lecture seule.

L'autre moyen d'y accéder est le nouveau périphérique de caractère /dev/kmsg. Il s'agit d'une interface de lecture-écriture qui peut être partagée entre plusieurs processus client. Si plusieurs processus le partagent, ils lisent tous le même flux de données complet, sans être affectés les uns par les autres. S'ils l'ouvrent pour un accès en écriture, ils peuvent également injecter des messages dans le flux de journaux du noyau, comme s'ils étaient générés par le noyau.

/proc/kmsg Et /dev/kmsg Fournissent des données de journal sous une forme non RFC-5424.

Applications

Les applications ont changé.

La fonction GNU C de la bibliothèque syslog() dans les principales tentatives de connexion à une prise de datagramme AF_LOCAL Nommée /dev/log Et y écrit des entrées de journal . (La fonction syslog() de la bibliothèque BSD C utilise de nos jours /var/run/log Comme nom de socket, et essaie d'abord /var/run/logpriv.) Les applications peuvent bien sûr avoir leur propre code pour le faire directement La fonction de bibliothèque est juste du code (pour ouvrir, se connecter, écrire et fermer un socket) s'exécutant dans le contexte de processus de l'application, après tout.

Les applications peuvent également envoyer des messages RFC 5424 via UDP à un serveur RFC 5426 local, si l'on écoute sur un socket datagramme AF_INET/AF_INET6 Sur la machine.

Grâce à la pression du monde daemontools au cours des deux dernières décennies, de nombreux dæmons prennent en charge l'exécution dans un mode où ils n'utilisent pas la fonction de bibliothèque C GNU syslog() C, ou des sockets UDP, mais crachez simplement leurs données de journal sur l'erreur standard de la manière Unix ordinaire.

gestion des logs avec nosh et la famille daemontools en général

Avec la famille de jeux d'outils daemontools, la journalisation est très flexible. Mais en général, dans toute la famille, l'idée est que chaque démon "principal" a un démon "d'enregistrement" associé. les dæmons "principaux" fonctionnent exactement comme les processus non-dæmon et écrivent leurs messages de journal dans l'erreur standard (ou la sortie standard), que le sous-système de gestion des services prévoit de connecter via un canal (qu'il maintient ouvert afin que les données de journal ne soient pas perdues) un redémarrage du service) à l'entrée standard du démon "logging".

Tous les démons de "journalisation" exécutent un programme qui enregistre quelque part. Généralement, ce programme est quelque chose comme multilog ou cyclog qui lit à partir de son entrée standard et écrit des fichiers journaux (horodatés en nanosecondes) dans un répertoire strictement limité en taille, tourné automatiquement et en écriture exclusive. En règle générale, également, ces démons s'exécutent tous sous l'égide de comptes d'utilisateurs dédiés non privilégiés.

On se retrouve donc avec un système de journalisation largement distribué, avec les données de journal de chaque service traitées séparément.

Un peut exécuter quelque chose comme klogd ou syslogd ou rsyslogd sous une gestion de services de la famille daemontools. Mais le monde des daemontools a réalisé il y a de nombreuses années que la structure de gestion des services avec des démons de "journalisation" se prêtait très bien à faire les choses de manière plus simple. Il n'est pas nécessaire de ventiler tous les flux de journaux en un seul méli-mélo géant, d'analyser les données des journaux, puis de les redistribuer pour séparer les fichiers journaux; puis (dans certains cas) boulonner un mécanisme de rotation externe non fiable des billes sur le côté. La structure de la famille daemontools dans le cadre de sa gestion de journal standard le fait déjà la rotation du journal, l'écriture du fichier journal et la séparation des flux.

En outre: Le modèle de chargement de chaîne de suppression des privilèges avec des outils communs à tous les services signifie que les programmes de journalisation n'ont pas besoin de privilèges de superutilisateur; et le modèle UCSPI signifie qu'ils n'ont qu'à se soucier des différences telles que les transports de flux par rapport aux datagrammes.

Le jeu d'outils nosh en est un exemple. Alors que l'on peut exécuter rsyslogd en dessous, hors de la boîte, et gérer simplement le noyau, /run/log, Et l'entrée du journal UDP à l'ancienne; il aussi fournit plus de façons "natives daemontools" de consigner ces choses:

  • un service klogd qui lit à partir de /proc/kmsg et écrit simplement ce flux de journal dans son erreur standard. Cela se fait par un simple programme nommé klog-read. Le démon de journalisation associé alimente le flux de journaux sur son entrée standard dans un répertoire de journaux /var/log/sv/klogd.
  • un service local-syslog-read qui lit les datagrammes de /dev/log (/run/log sur les BSD) et écrit simplement ce flux de journal dans son erreur standard. Cela se fait par un programme nommé syslog-read. Le démon de journalisation associé alimente le flux de journaux sur son entrée standard dans un répertoire de journaux /var/log/sv/local-syslog-read.
  • un service udp-syslog-read qui écoute sur le port syslog UDP, lit ce qui lui est envoyé et écrit simplement ce flux de journal dans son erreur standard. Encore une fois, le programme est syslog-read. Le démon de journalisation associé alimente le flux de journaux sur son entrée standard dans un répertoire de journaux /var/log/sv/udp-syslog-read.
  • (sur les BSD) un service local-priv-syslog-read qui lit les datagrammes de /run/logpriv et écrit simplement ce flux de journal dans son erreur standard. Encore une fois, le programme est syslog-read. Le démon de journalisation associé alimente le flux de journaux sur son entrée standard dans un répertoire de journaux /var/log/sv/local-priv-syslog-read.

Le jeu d'outils est également livré avec un outil export-to-rsyslog Qui peut surveiller un ou plusieurs répertoires de journaux (en utilisant un système non intrusif curseurs de journaux) et envoyer de nouvelles entrées au format RFC 5424 sur le réseau à un serveur RFC 5426 désigné.

gestion des journaux avec systemd

systemd possède un seul programme de gestion des journaux monolithiques, systemd-journald. Cela fonctionne comme un service géré par systemd.

  • Il lit /dev/kmsg Pour les données du journal du noyau.
  • Il lit /dev/log (Un lien symbolique vers /run/systemd/journal/dev-log) Pour les données du journal des applications de la fonction syslog() de la bibliothèque C GNU C).
  • Il écoute sur le socket de flux AF_LOCAL À /run/systemd/journal/stdout Pour les données de journal provenant des services gérés par systemd.
  • Il écoute sur la prise de datagramme AF_LOCAL À /run/systemd/journal/socket Pour les données de journal provenant de programmes qui parlent le protocole de journal spécifique à systemd (c'est-à-dire sd_journal_sendv() et al.).
  • Il les mélange tous ensemble.
  • Il écrit dans un ensemble de fichiers journaux à l'échelle du système et par utilisateur, dans /run/log/journal/ Ou /var/log/journal/.
  • S'il peut se connecter (en tant que client) à une prise de datagramme AF_LOCAL À /run/systemd/journal/syslog, Il y écrit des données de journal, si le transfert vers syslog est configuré.
  • S'il est configuré, il écrit des données de journal dans la mémoire tampon du noyau à l'aide du mécanisme inscriptible /dev/kmsg.
  • S'il est configuré, il écrit également les données du journal sur les terminaux et le périphérique de la console.

De mauvaises choses se produisent à l'échelle du système si ce programme se bloque ou si le service est arrêté.

systemd lui-même organise les sorties standard et les erreurs de (certains) services à attacher à la socket /run/systemd/journal/stdout. Les utilisateurs qui se connectent normalement à l'erreur standard ont donc leur sortie envoyée au journal.

Cela supplante complètement klogd, syslogd, syslog-ng et rsyslogd.

Ceux-ci doivent désormais être spécifiques à systemd. Sur un système systemd, ils ne deviennent pas l'extrémité serveur de /dev/log. Au lieu de cela, ils adoptent l'une des deux approches:

  • Ils deviennent le serveur de /run/systemd/journal/syslog, Qui (si vous vous en souvenez) systemd-journald Tente de se connecter et d'écrire des données de journal. Il y a quelques années, on aurait configuré la méthode d'entrée imuxsock de rsyslogd pour ce faire.
  • Ils lisent directement à partir du journal systemd, à l'aide d'une bibliothèque spécifique à systemd qui comprend le format de journal binaire et qui peut surveiller les fichiers journaux et le répertoire pour les nouvelles entrées ajoutées. De nos jours, on configure la méthode d'entrée imjournal de rsyslogd pour ce faire.
58
JdeBP