Например, демон может сделать следующий вызов, когда вызов функции
rename
неожиданно оказывается неудачным:
syslog(LOG_INFO|LOG_LOCAL2, "rename(%s, %s): %m", file1, file2);
Назначение аргументов
facility
и
level
в том, чтобы все сообщения, которые посылаются процессами определенного типа (то есть с одним значением аргумента
facility
), могли обрабатываться одинаково в файле
/etc/syslog.conf
или чтобы все сообщения одного уровня (с одинаковым значением аргумента
level
) обрабатывались одинаково. Например, файл конфигурации
может содержать строки
kern.* /dev/console
local7.debug /var/log/cisco.log
для указания, что все сообщения ядра направляются на консоль, а сообщения относительно отладки со значением аргумента
facility
, равным
local7
, добавляются в файл
/var/log/cisco.log
.
Когда приложение впервые вызывает функцию
syslog
, она создает дейтаграммный доменный сокет Unix и затем вызывает функцию
connect
для сокета с заранее известным полным именем, которое создано демоном
syslogd
(например,
/var/run/log
). Этот сокет остается открытым, пока процесс не завершится. Другим вариантом является вызов процессом функций
openlog
и
closelog
.
#include <syslog.h>
void openlog(const char * ident, int options, int facility);
void closelog(void);
Функция
openlog
может быть вызвана перед первым вызовом функции
syslog
, а функция
closelog
— когда приложение закончит отправлять сообщения в журнал.
Аргумент
ident
— это строка, которая будет добавлена в начало каждого журнального сообщения функцией
syslog
. Часто это имя программы.
Обычно аргумент
options
формируется путем применения операции логического ИЛИ к константам из табл. 13.3.
Таблица 13.3. Аргумент options (параметр) для функции openlog
Параметр | Описание |
LOG_CONS | Выводить журнал на консоль, если невозможно послать сообщение демону syslogd |
LOG_NDELAY | Не откладывать создание сокета, открыть его сейчас |
LOG_PERROR | Записывать сообщение в stderr, а также посылать его демону syslogd |
LOG_PID | Включать идентификатор процесса (PID) в каждую запись журнала |
Обычно доменный сокет Unix не создается при вызове функции
openlog
. Вместо этого сокет открывается при первом вызове функции
syslog
. Параметр
LOG_NDELAY
указывает, что сокет должен создаваться при вызове функции
openlog
.
Аргумент
facility
функции
openlog
задает значение
facility
, используемое по умолчанию для любого последующего вызова функции
syslog
, при котором не задается аргумент
facility
. Некоторые демоны вызывают функцию
openlog
и задают значение аргумента
facility
(которое
обычно не изменяется для данного демона) и затем в каждом вызове функции
syslog
задают только аргумент
level
(поскольку
level
может изменяться в зависимости от ошибки).
Сообщения для записи в журнал могут также генерироваться командой
logger
. Это может использоваться в сценариях интерпретатора команд, например для отправки сообщений демону
syslogd
.
13.4. Функция daemon_init
В листинге 13.1 [1] показана функция, называемая
daemon_init
, которую мы можем вызвать (обычно с сервера), чтобы придать процессу свойства демона.
Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
Листинг 13.1. Функция daemon_init: придание процессу свойств демона
//daemon _init.с
1 #include "unp.h"
2 #include <syslog.h>
3 #define MAXFD 64
4 extern int daemon_proc; /* определен в error.с */
5 int
6 daemon_init(const char *pname, int facility)
7 {
8 int i;
9 pid_t pid;
10 if ((pid = Fork) < 0)
11 return (-1);
12 else if (pid)
13 _exit(0); /* родитель завершается */
14 /* 1-й дочерний процесс продолжает работу... */
15 if (setsid < 0) /* становится главным процессом сеанса */
16 return (-1);
17 Signal(SIGHUP, SIG_IGN);
18 if ((pid = Fork) < 0)
19 return (-1);
20 else if (pid)
21 _exit(0); /* 1-й дочерний процесс завершается */
22 /* 2-й дочерний процесс продолжает работу */
23 daemon_proc = 1; /* для функций err_XXX */
24 chdir("/"); /* смена текущего каталога */
25 /* закрытие дескрипторов файлов*/
26 for (i = 0; i < MAXFD; i++)
27 close(i);
28 /* перенаправление stdin, stdout и stderr в /dev/null */
29 open("/dev/null", O_RDONLY);
30 open("/dev/null", O_RDWR);
31 open("/dev/null", O_RDWR);