Решением обеих этих проблем является создание обработчика сигнала SIGHUP и выполнение внутри него всех необходимых шагов. В разделе 34.4 отмечалось, что сигнал SIGHUP генерируется для контролирующего процесса при отключении его от контролирующего терминала. Поскольку демоны лишены соединения с терминалом, они никогда не получают этот сигнал и могут использовать его в целях, описанных в данном разделе.
Для автоматической ротации журнальных файлов демона можно применить программу logrotate. Подробности ищите на справочной странице logrotate(8).
В листинге 37.3 приводится пример того, каким образом демон может использовать сигнал SIGHUP. Программа устанавливает обработчик SIGHUP
Для лаконичности функции logOpen(), logClose(), logMessage() и readConfigFile() не вошли в листинг 37.3, но вы можете найти их в архиве с исходным кодом, который прилагается к этой книге. О назначении первых трех из них можно догадаться по их именам, а функция readConfigFile() просто считывает строчку из конфигурационного файла и записывает ее в журнал.
Некоторые демоны используют альтернативный метод повторной инициализации при получении сигнала SIGHUP, закрывая все файлы и перезапускаясь с помощью вызова exec().
Ниже представлен пример работы программы из листинга 37.3. Сначала мы создаем фиктивный конфигурационный файл, после чего запускается демон:
$ echo START > /tmp/ds.conf
$ ./daemon_SIGHUP
$ cat /tmp/ds.log
2011-01–17 11:18:34: Opened log file
2011-01–17 11:18:34: Read config file: START
Теперь, прежде чем отправить демону сигнал SIGHUP, изменим конфигурационный файл и переименуем журнал:
$ echo CHANGED > /tmp/ds.conf
$ date +'%F %X'; mv /tmp/ds.log /tmp/old_ds.log
2011-01–17 11:19:03 AM
$ date +'%F %X'; killall — HUP daemon_SIGHUP
2011-01–17 11:19:23 AM
$ ls /tmp/*ds.log
/tmp/ds.log /tmp/old_ds.log
$ cat /tmp/old_ds.log
2011-01–17 11:18:34: Opened log file
2011-01–17 11:18:34: Read config file: START
2011-01–17 11:18:49: Main: 1
2011-01–17 11:19:04: Main: 2
2011-01–17 11:19:19: Main: 3
2011-01–17 11:19:23: Closing log file
Вывод команды ls показывает наличие как старого, так и нового журнального файла. Просматривая старый журнал с помощью утилиты cat, мы можем увидеть, что даже после ввода команды mv для переименования файла демон продолжает записывать в него сообщения. На этом этапе старый журнальный файл можно удалить, если он нам больше не нужен. Содержимое нового журнала указывает на то, что конфигурационный файл был прочитан заново:
$ cat /tmp/ds.log
2011-01–17 11:19:23: Opened log file
2011-01–17 11:19:23: Read config file: CHANGED
2011-01–17 11:19:34: Main: 4
$ killall daemon_SIGHUP
Обратите внимание на то, что журнальный и конфигурационный файлы демонов обычно размещаются в стандартных каталогах, а не в /tmp, как это сделано в программе из листинга 37.3. Конфигурацию принято хранить в каталоге /etc или в одном из его подкаталогов, а журнал часто находится в /var/log. Программы-демоны обычно предоставляют параметры командной строки, которые позволяют указать альтернативные пути вместо стандартных.
Листинг 37.3. Использование сигнала SIGHUP для повторной инициализации демона
daemons/daemon_SIGHUP.c
#include
#include
#include "become_daemon.h"
#include "tlpi_hdr.h"
static const char *LOG_FILE = "/tmp/ds.log";
static const char *CONFIG_FILE = "/tmp/ds.conf";
/* Определения функций logMessage(), logOpen(), logClose()
и readConfigFile() в этом листинге опущены */
static volatile sig_atomic_t hupReceived = 0;
/* При получении SIGHUP устанавливаем ненулевое значение */
static void
sighupHandler(int sig)
{
}
int
main(int argc, char *argv[])
{
const int SLEEP_TIME = 15; /* Период бездействия между сообщениями */
int count = 0; /* Количество завершенных интервалов SLEEP_TIME */
int unslept; /* Время, оставшееся до завершения периода бездействия */
struct sigaction sa;
sigemptyset(&sa.sa_mask);