Назад | Перейти на главную страницу

Должна ли программа переднего плана, вызываемая демоном, разделять ведение журнала между stderr и stdout на основе уровней серьезности?

Обычно сообщения журнала записываются в stderr. Мне интересно, является ли хорошей идеей / практикой разделять сообщения журнала, чтобы ошибки и предупреждения отправлялись на stderr, а сообщения отладки / информационные / уведомления вместо этого отправлялись на stdout? Или это не имеет значения, учитывая, что многие выделенные процессы ведения журнала в любом случае читают только из stdin, что требует объединения сообщений исходного журнала в stderr и stdout и перенаправления на stdin регистратора.

[Обновить]

В двух приведенных ниже ответах упоминается системный журнал, я думаю, мне нужно подробно разъяснить настройку.

Запрошенные мной процессы-демоны сами по себе работают на переднем плане. Демонизация управляется контролирующими процессами, такими как runit или supervisord. В обоих случаях stderr и stdout процессов демона будут захвачены контролирующими процессами, и задача контролирующих процессов - решить, как и где хранить журналы (может быть syslog или где-то еще в сети через UDP) . Процессам-демонам не нужно беспокоиться о том, что и где писать журналы, они просто пишут в stdout / stderr.

В случае runit, его лесозаготовительный комплекс svlogd будет читать из своего стандартного ввода-вывода перенаправленные сообщения журнала, которые объединены в стандартный / стандартный вывод управляемого процесса демона. Что касается supervisord, он может записывать stderr и stdout в отдельные файлы журнала.

Итак, в этих конкретных настройках, рекомендуется ли разделять журналы между stderr и stdout или просто записывать в один из них?

Во-первых, кое-что важно прояснить: STDOUT и STDERR редко актуальны в контексте процесса демона после его успешного запуска, если вы не вызываете его с помощью переключателя отладки.

Вся суть демона в том, что он должен отмежеваться от управляющего терминала, чтобы он мог сохраняться после выхода из системы. Если терминала нет, все сообщения должны быть отправлены либо демону системного журнала, либо файлу журнала, управляемому непосредственно процессом.

Если вы на самом деле не имеете в виду демонов, а на самом деле имеете в виду любой сценарий оболочки или что-то подобное, которое вы пишете самостоятельно, то логика обычно должна быть такой:

  • STDOUT: Все, что вы хотите перехватить с помощью каналов или основного перенаправления вывода.
  • STDERR: "Внешние" сообщения. Вещи, которые вы все равно хотите, чтобы попасть на чей-то терминал, даже если они выполняют какое-то перенаправление. (следовательно, почему они связаны с ошибками). Позвольте пользователю решить, хотят ли они также перенаправить эти сообщения, т. е. перенаправить STDERR к STDIN как вы упомянули.

Я бы не советовал смешивать stdout и stderr внутри ваша программа, но как вы с ней справляетесь вне на ваше усмотрение. stdout был предназначен для обработки данных, предназначенных для конвейера, а stderr специально для сообщений без данных. Это делает возможным определенное поведение, такое как пакетная обработка, без изменения существующего интерактивного поведения. Ваш случай отличается - велика вероятность, что stdout практически ничего не значит.

Так как runit имеет немного другой взгляд на ведение журнала через svlog, и служба, которую вы пишете, скорее всего, не будет демонизировать (что в данном случае означает «отсоединение от tty»), тогда вам решать, хотите ли вы записать все в один журнал или нет, через /etc/sv/<servicename>/run сценарий. По большей части большинство запускаемых скриптов используют

exec 2>&1 

чтобы объединить два потока вместе, поскольку большинство служб не передают данные через стандартный вывод. Если вы хотите использовать svlog вам нужно будет создать сценарий на /etc/sv/<servicename>/log/run с соответствующей командой, чтобы запустить его. Вероятно, это выглядит примерно так (но не совсем так):

#!/bin/sh
exec 2>&1
exec svlog -tt main

где main символическая ссылка на каталог журналов.

Если это демон, я рекомендую использовать интерфейс syslog для записи ваших сообщений прямо в журналы. Для получения информации запустите "man 3 syslog". Если необходимо, ваша программа также может иметь параметр отладки (с параметром, определяющим приоритет), который сообщает программе-демону, что она не запускается в фоновом режиме, а также регистрируется в stderr.

Я бы написал функцию ведения журнала, которая принимает в качестве аргумента приоритет и строку. Он должен вызвать syslog (), чтобы правильно зарегистрировать сообщение, и если приоритет больше или равен значению глобального приоритета отладки, вывести сообщение в stderr, а также в syslog (). Вызов syslog(..., "%s", msg) чтобы символы процента в сообщении не были ошибочными. (Или пусть ваша функция принимает переменное количество аргументов и передает список аргументов в vsyslog ().)

Убедитесь, что вы звоните openlog(..., LOG_PID, LOG_DAEMON) при инициализации вашей программы. Вы могли бы добавить | LOG_PERROR после LOG_DAEMON, если вы находитесь в режиме отладки, что позволит избежать необходимости писать функцию ведения журнала, упомянутую выше. Но тогда вы потеряете возможность фильтровать по приоритету.

Возможно (при использовании Ubuntu) вам потребуется настроить /etc/rsyslog.conf чтобы гарантировать, что сообщения демона регистрируются.

PS - Используйте команду logger, если ваш демон является сценарием оболочки

Я не думаю, что вам следует использовать для ведения журнала и stdout, и stderr. Если у вас есть сообщения журнала с разной степенью серьезности, они должны быть помечены префиксом, чтобы их было легко фильтровать / сортировать с помощью svlogd.

Я бы сказал, что использование stdout и stderr для ведения журнала нарушит принцип наименьшего удивления.