Linux-демон и STDIN / STDOUT - PullRequest
       5

Linux-демон и STDIN / STDOUT

9 голосов
/ 02 февраля 2011

Я работаю над демоном linux и у меня есть некоторые проблемы с stdin / stdout. Обычно из-за характера демона у вас нет ни stdin, ни stdout. Однако в моем демоне есть функция, которая вызывается при первом запуске демона, чтобы указать другие параметры, необходимые для успешной работы демона. Когда эта функция вызывается, терминал становится настолько вялым, что мне приходится запускать отдельную оболочку и убивать демона с помощью top, чтобы получить ответную подсказку. Теперь я подозреваю, что это как-то связано с процессом разветвления, закрывающим stdin / stdout, но я не совсем уверен, как мне обойти это. Если бы вы, ребята, могли бы пролить некоторый свет на ситуацию, которая была бы наиболее ценной. Спасибо.

Edit:

int main(argc, char *argv[]) {

/* setup signal handling */

/* check command line arguments */

pid_t pid, sid;

pid = fork();

if (pid < 0) {
exit(EXIT_FAILURE);
}

if(pid > 0){
exit(EXIT_SUCCESS);
}

sid = setsid();

if(sid < 0) {
exit(EXIT_FAILURE);
}

umask(027);

/* set syslogging */

/* do some logic to determine wether we are running the daemon for the first time and if we are call the one time function which uses fgets() to recieve some input */

while(1) {

/* do required work */

}

/* do some clean up procedures and exit */

return 0;
}

Ребята, вы упомянули использование файла конфигурации. Это именно то, что я делаю, чтобы сохранить параметры, полученные через ввод. Однако мне все еще нужно получить их от пользователя через стандартный ввод. Логика определения того, работаем ли мы в первый раз, основана на существовании файла конфигурации.

Ответы [ 6 ]

14 голосов
/ 02 февраля 2011

Обычно стандартный вход демона должен быть подключен к /dev/null, так что если что-то читается со стандартного входа, вы сразу получаете EOF.Обычно стандартный вывод должен быть связан с файлом - либо файлом журнала, либо /dev/null.Последнее означает, что все записи будут выполнены успешно, но информация не будет сохранена.Аналогично, стандартная ошибка должна быть подключена к /dev/null или к файлу журнала.

Все программы, включая демонов, имеют право предполагать, что stdin, stdout и stderr являются соответственно открытыми файловыми потоками.

Обычно для демона целесообразно контролировать, откуда поступают его входные данные и куда выводятся выходные данные.Редко появляется повод для ввода, отличного от /dev/null.Если код был написан для выживания без стандартного вывода или стандартной ошибки (например, он открывает стандартный канал журнала или, возможно, использует syslog(3)), тогда может быть целесообразно закрыть stdout и stderr.В противном случае, вероятно, целесообразно перенаправить их на /dev/null, сохраняя при этом сообщения в файле журнала.В качестве альтернативы, вы можете перенаправить как stdout, так и stderr в файл журнала - остерегайтесь постоянно растущих файлов журнала.

Время отклика от невозможности до невозможности может быть связано с тем, что ваша программа не обращает внимания на EOF в цикле чтения,Это может быть запрос на ввод данных пользователем в / dev / null и чтение ответа из / dev / null, а не возвращение «y» или «n», он пытается снова, что ужасно жует вашу систему.Конечно, код имеет недостатки в том, что он не обрабатывает EOF и подсчитывает, сколько раз он получает неправильный ответ, и перестает быть глупым после разумного количества попыток (16, 32, 64).Программа должна разумно и безопасно закрыть магазин, если ожидает значимого ввода и продолжает его не получать.

3 голосов
/ 02 февраля 2011

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

Вместо чтения стандартного ввода, естьпользователь сам пишет файл конфигурации;проверьте его существование перед разветвлением и выйдите с ошибкой, если это не так.Включите пример файла конфигурации с демоном и запишите его формат на справочной странице вашего демона.У вас есть справочная страница, да?Ваш конфигурационный файл является текстовым, да?

Кроме того, в вашей логике демонизации отсутствует ключевой шаг.После разветвления, но перед вызовом setsid вам нужно закрыть fds 0, 1 и 2 и снова открыть их для /dev/null (не пытайтесь сделать это с fclose и fopen),Это должно исправить вашу вялую проблему с терминалом.

2 голосов
/ 03 мая 2016

Если вы хотите запустить вашу программу отдельно, используйте оболочку : (setsid <command> &).Не fork() внутри вашей программы, что вызовет кошмар сисадмина .

Не используйте syslog() и перенаправление stdout или stderr.

Еще лучше, используйте менеджер демонов , например, инструменты демона, runit, OpenRC и systemd, чтобы демонизировать вашу программу для вас.

1 голос
/ 02 февраля 2011

Если вы настаиваете на использовании ввода stdin / клавиатура для запуска демона (например, чтобы получить магическую фразу-пароль, которую вы не хотите хранить в файле), тогда обрабатывайте все операции ввода-вывода до the fork().

1 голос
/ 02 февраля 2011

Использовать файл конфигурации. Не используйте STDIN или STDOUT с демоном. Демоны предназначены для работы на фоне без взаимодействия с пользователем.

1 голос
/ 02 февраля 2011

Ваш дизайн не так. Процессы демона не должны получать ввод через stdin или доставлять вывод в stdout / stderr. Вы закроете эти дескрипторы как часть фазы демонизации. Демоны должны получать параметры конфигурации из командной строки, файла конфигурации или обоих. Если требуется ввод во время выполнения, вам придется прочитать файл, открыть сокет и т. Д., Но суть демона в том, что он должен иметь возможность запускать и выполнять свою работу без присутствия пользователя на консоли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...