Получить вывод в журнал в службе на языке C

Вопрос или проблема

У меня есть небольшой сервис, написанный на C под Debian.
Этот сервис автоматически запускается с Linux и выполняет некоторые операции с файлами и другие ожидаемые задачи.
Сервис выводит некоторые информационные сообщения и также сообщения об ошибках в стандартный вывод. Это видно в консольном окне, когда я запускаю бинарный файл из консоли, а не как сервис.

Единственное, что мне пока не удалось сделать, это записать его вывод в журнал, когда бинарный файл запускается как сервис.

Я прошелся по всем найденным материалам, я выполняю запрос журнала от имени root и вижу системные сообщения о начале/остановке сервиса, но ничего из того, что печатает бинарник сервиса.
Я просто вывожу с помощью printf("привет, это должно появиться в журнале"); – но в журнале ничего не видно.

Согласно тому, что объясняется повсюду, весь вывод сервиса должен автоматически направляться в журнал, верно?
Что я могу пропустить, чтобы это не произошло?

Правка
Я нашел специальные функции для ведения журнала, но мне на самом деле нравится идея получать стандартный вывод автоматически, либо в консоли, либо в журнале, в зависимости от того, как я запускаю бинарный файл.
Я пробовал сервис на bash-скрипте и заметил, что он записывает сообщения echo в журнал, как и ожидалось.

При запуске с использованием systemd стандартный вывод юнита направляется туда, куда указывает настройка StandardOutput=. По умолчанию это значение, заданное в системной конфигурации DefaultStandardOutput=, а это по умолчанию равно journal. Поэтому, если ваша система использует настройки по умолчанию, стандартный вывод юнитов должен идти в журнал.

Для любого данного юнита вы можете проверить эту настройку, выполнив

systemctl show -P StandardOutput вашюнит

(заменив вашюнит на соответствующее значение).

Одно из вещей, которые стоит проверить, – это очищает ли ваша программа свой вывод: с помощью printf вам нужно включить символ новой строки (\n) или явно вызвать fflush.

В общем случае сообщения журнала должны записываться с использованием syslog, а не отправляться в стандартный вывод; см. Правильный способ написания кода на C, который вставляет сообщение в /var/log/messages? для подробностей.

Ответ или решение

Чтобы вывод вашего сервиса на языке C отображался в системном журнале, когда запущен как служба в системе, вам нужно учесть несколько моментов.

1. Конфигурация сервиса systemd:

Когда служба запускается через systemd, стандартный вывод (stdout) и стандартный поток ошибок (stderr) должны перенаправляться в журнал по умолчанию. Для этого в файле конфигурации службы (юнит-файле) проверьте настройки StandardOutput и StandardError. Обычные настройки по умолчанию направляют вывод в журнал. Вы можете использовать следующую команду для проверки текущих настроек вашего юнит-файла:

systemctl show -P StandardOutput имя_вашей_службы
systemctl show -P StandardError имя_вашей_службы

Если настройки не равны journal, вы можете задать их явно в своем юнит-файле:

[Service]
ExecStart=/path/to/your/executable
StandardOutput=journal
StandardError=journal

Не забудьте перезагрузить конфигурации systemd:

sudo systemctl daemon-reload

2. Поток вывода:

Когда вы используете printf, убедитесь, что вывод буферизуется должным образом. Как правило, при отсутствии новой строки (\n) или явного вызова fflush(stdout), данные могут не поступать в журнал. Например:

printf("Привет, это сообщение должно появиться в журнале.\n");

Либо:

printf("Привет, это сообщение должно появиться в журнале.");
fflush(stdout);

Это гарантирует, что данные попадают в поток вывода вовремя.

3. Альтернативный подход: использование syslog:

Если вы хотите более надежный и стандартный способ ведения логов, рассмотрите возможность использования библиотеки syslog. Это позволит вашему приложению записывать сообщения непосредственно в системный журнал (например, /var/log/syslog). Пример использования:

#include <syslog.h>

int main() {
    // Открыть syslog
    openlog("Имя программы", LOG_PID|LOG_CONS, LOG_USER);

    // Запись сообщения в syslog
    syslog(LOG_INFO, "Привет, это сообщение в syslog.");

    // Закрытие syslog
    closelog();

    return 0;
}

4. Проверка логов:

После внесения изменений можно проверить логи с помощью:

journalctl -u имя_вашей_службы

Таким образом, следуя этим шагам, вы сможете отправлять вывод вашего сервиса на языке C в системный журнал, как при его запуске как службы, так и из консоли.

Оцените материал
Добавить комментарий

Капча загружается...