Шаг 12 - Вывод сообщений об ошибках программы

Сообщения об ошибках один из методов анализа правильности работы программы. Причем это не только сообщения для пользователя, но и сообщения об ошибках на этапе отладки приложения при разработке.

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

Все это конечно хорошо, если Вы разрабытаваете пользовательское консольное приложение, но как быть, если Ваша программа является сетевым приложением, например POP3 или каким-нибудь другим сервером. В этом случае работа с stderr не возможна, и отладка мягко выражаясь может сильно усложниться. Но не все так печально. Для этих случаев существует демон сообщений syslogd, который все сообщения от ядра и программ записывает в файлы хранящиеся в папке /var/log.

Для того, чтобы начать работу с этим демоном надо подключить файл syslog.h и вам станут доступными три процедуры:


#include <syslog.h>

void openlog( char *ident, int option, int  facility)

void syslog( int priority, char *format, ...)

void closelog( void )

Предназначение функции closelog() думаю ясно, она закрывает дескриптор, который использовался для передачи сообщений в system logger. Ее использование опционально и, если вы забудете ее вызвать, то ничего катастрофичного не произойдет.

Для начала вывода сообщений Вам придется передать в функцию openlog() несколько необходимых параметров:

Вызов функции openlog() также не обязателен, она будет автоматически вызвана при необходимости во время использования syslog(), но идентификатор программы будет установлен в NULL, что я думаю не будет считаться хорошим тоном.

Ну, и чтобы выводить сами сообщения надо использовать функцию syslog(), работа с которой похожа на работу с функцией printf, за исключением того, что сообщению можно задать приоритет(или тип), т.е. его важность. Задается приоритет параметром priority, который может иметь следующие значения:

А теперь попробуем написать программу test.c, использующую syslog:


#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>

#define DEBUG

int main() {

    int i=0;
    openlog("test", LOG_PID, LOG_USER);

#ifdef DEBUG
    syslog(LOG_DEBUG,"try to sending 10 messages");
#endif

    for (i=0; i < 10; i++){
        syslog(LOG_INFO, "info message [i = %d] ", i);
    };

#ifdef DEBUG
    syslog(LOG_DEBUG,"try log to stderr");
#endif
    closelog();

    openlog("test_stderr",LOG_PERROR | LOG_PID,LOG_USER);
    syslog(LOG_INFO,"this is attempt to use stderr for syslog");
    closelog();

    return 0;
};

Компилируем программу и попробуем запустить:

dron~# ./test
test_stderr[6222]: this is attempt to use stderr for syslog

Теперь можем зайти в файл /var/log/messages и посмотреть, что там получилось. А получилось вот что:

Dec 20 11:25:04 dron-linux test[6222]: info message [i = 0]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 1]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 2]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 3]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 4]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 5]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 6]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 7]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 8]
Dec 20 11:25:04 dron-linux test[6222]: info message [i = 9]
Dec 20 11:25:04 dron-linux test_stderr[6222]: this is attempt to use stderr for syslog

Помоему классно, но почему-то не хватает некоторых сообщений. Посмотрим /var/log/debug и увидим, что все на месте :)

Dec 20 11:25:04 dron-linux test[6222]: try to sending 10 messages
Dec 20 11:25:04 dron-linux test[6222]: try log to stderr

То есть тут мы можем увидеть, что сообщения разных типов выводятся в разные файлы. Настроить это можно с помощью файла /etc/syslog.conf. К примеру в данном случае он выглядит вот так:

# /etc/syslog.conf
# For info about the format of this file, see "man syslog.conf"
*.=info;*.=notice	/var/log/messages
*.=debug		/var/log/debug
*.err			/var/log/syslog

Обратите также внимание, что сообщения, которые должны были выводиться в stderr дублируются в файл. Т.е. по большому счету, даже если поток stderr будет не доступен, то сообщения программы все равно дойдут до вас и это очень хорошо.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Кузин Андрей - 22.12.2002