Книга: Разработка приложений в среде Linux. Второе издание

12.5. Повторное открытие журнальных файлов

12.5. Повторное открытие журнальных файлов

Большинство системных демонов ведут журнальные файлы, записывая в них все, что они делают. Поскольку многие системы Unix месяцами работают без остановки, эти журнальные файлы могут стать достаточно большими. Простое периодическое удаление (или переименование) журнальных файлов — не самое хорошее решение, потому что демоны будут продолжать записывать в эти файлы, несмотря на их недоступность, а необходимость останавливать и запускать каждый демон для очистки журнальных файлов приводит к недоступности системы (хоть и на незначительное время). Общий способ для демонов справиться с упомянутой ситуацией — перехватывать SIGHUP и повторно открывать журнальные файлы. Это позволяет организовать ротацию журналов (периодическое открытие новых журнальных файлов при сохранении старых), используя простой сценарий вроде приведенного ниже.

dd /var/log
mv messages messages.old
killall -HUP syslogd

Logrotate (ftp://ftp.redhat.com/pub/redhat/code/logrotate/) — одна из программ, которая использует преимущество такого метода для выполнения безопасной ротации журналов.

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

Затем обработчик сигнала SIGHUP в своем вызове устанавливает эту переменную, и главная часть программы проверяет эту переменную насколько можно часто. Ниже приведен пример соответствующей программы.

 1: /*sighup.c*/
 2:
 3: #include <errno.h>
 4: #include <signal.h>
 5: #include <stdio.h>
 6: #include <string.h>
 7: #include <unistd.h>
 8:
 9: volatile int reopenLog = 0; /* volatile - поскольку модифицируется
10:                                обработчиком сигнала */
11:
12: /* записать строку в журнал */
13: void logstring(int logfd, char *str) {
14:  write(logfd, str, strlen(str));
15: }
16:
17: /* когда приходит SIGHUP, сделать запись об этом и продолжить */
18: void hupHandler(int signum) {
19:  reopenLog = 1;
20: }
21:
22: int main() {
23:  int done = 0;
24:  struct sigaction sa;
25:  int rc;
26:  int logfd;
27:
28:  logfd = STDOUT_FILENO;
29:
30:  /* Установить обработчик сигнала SIGHUP. Использовать memset() для
31:     инициализации структуры sigaction чтобы обеспечить очистку
32:     всего. */
33:  memset(&sa, 0, sizeof(sa));
34:  sa.sa_handler = hupHandler;
35:
36:  if (sigaction(SIGHUP, &sa, NULL)) perror("sigaction");
37:
38:  /* Записывать сообщение в журнал каждые две секунды, и
39:     повторно открывать журнальный файл по требованию SIGHUP */
40:  while (!done) {
41:   /*sleep() возвращает не ноль, если не спит достаточно долго*/
42:   rc = sleep(2);
43:   if (rc) {
44:    if (reopenLog) {
45:     logstring(logfd,
46:      "* повторное открытие журналов по запросу SIGHUPn");
47:     reopenLog = 0;
48:    } else {
49:     logstring(logfd,
50:      "* sleep прервано неизвестным сигналом "
51:      "--dyingn");
52:     done=1;
53:    }
54:   } else {
55:    logstring(logfd, "Периодическое сообщениеn");
56:   }
57:  }
58:
59:  return 0;
60: }

Чтобы протестировать эту программу, запустите ее в одном окне xterm и отправьте сигнал SIGHUP из другого. Для каждого сигнала SIGHUP, который принимает программа, она печатает сообщение, когда выполняет нормальную ротацию своих журналов. Помните, что если сигнал поступает в тот момент, когда работает другой экземпляр обработчика, доставляется только один экземпляр сигнала, поэтому не отправляйте их слишком часто.

Оглавление книги


Генерация: 1.545. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз