Шрифт:
Использование демона syslogd для вывода сообщений об ошибках
32
Вызывается функция openlog
. Первый ее аргумент берется из вызывающего процесса и обычно является именем программы (например, argv[0]
). Мы указываем, что идентификатор процесса должен добавляться к каждому сообщению. Аргумент facility
также задается вызывающим процессом, и его значением может быть константа из табл. 13.2 либо, если приемлемо значение по умолчанию LOG_USER
, нулевое значение. Отметим, что поскольку демон выполняется без управляющего терминала, он никогда не должен получать сигнал
SIGHUP
от ядра. Следовательно, многие демоны используют этот сигнал в качестве уведомления от администратора, что файл конфигурации демона изменился и демон должен еще раз считать файл. Два других сигнала, которые демон никогда не должен получать, — это сигналы SIGINT
и SIGWINCH
, и они также могут использоваться для уведомления демона о некоторых изменениях. Пример: сервер времени и даты в качестве демона
В листинге 13.2 представлено изменение нашего сервера времени и даты, не зависящего от протокола. В отличие от сервера, показанного в листинге 11.8, в нем вызывается функция
daemon_init
, чтобы этот сервер мог выполняться в качестве демона. Листинг 13.2. Не зависящий от протокола сервер времени и даты, работающий в качестве демона
//inetd/daytimetcpsrv2.c
1 #include "unp.h"
2 #include <time.h>
3 int
4 main(int argc, char **argv)
5 {
6 int listenfd, connfd;
7 socklen_t addrlen, len;
8 struct sockaddr *cliaddr;
9 char buff[MAXLINE];
10 time_t ticks;
11 daemon_init(argv[0], 0);
12 if (argc == 2)
13 listenfd = Tcp_listen(NULL, argv[1], &addrlen);
14 else if (argc == 3)
15 listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
16 else
17 err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>");
18 cliaddr = Malloc(addrlen);
19 for (;;) {
20 len = addrlen;
21 connfd = Accept(listenfd, cliaddr, &len);
22 err_msg("connection from %s", Sock_ntop(cliaddr, len));
23 ticks = time(NULL);
24 snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
25 Write(connfd, buff, strlen(buff));
26 Close(connfd);
27 }
28 }
Изменений всего два: мы вызываем нашу функцию
daemon_init
, как только программа запускается, а затем вызываем нашу функцию err_msg
вместо printf
, чтобы вывести IP-адрес и порт клиента. На самом деле, если мы хотим, чтобы наши программы могли выполняться как демоны, мы должны исключить вызов функций printf
и fprintf
и вместо них использовать нашу функцию err_msg
. Обратите внимание, что мы проверяем argc и выводим соответствующее сообщение до вызова
daemon_init
. Таким образом пользователь, запустивший демона, получает немедленное уведомление о недопустимом количестве аргументов. После вызова daemon_init
все сообщения направляются в системный журнал. Если мы запустим эту программу на нашем узле
linux
и затем проверим файл /var/log/messages
(куда мы отправляем все сообщения LOG_USER
) после соединения с тем же узлом, мы получим: