Запуск процесса в фоновом режиме в Linux с C

Я пытаюсь сделать что-то немного странно здесь. Мне нужно запустить процесс, logcat, из deamon, который будет работать в фоновом режиме и печатать на терминал без контроля stdin. Это для ведения журнала, поэтому в идеале logcat будет печатать сообщения журнала, позволяя пользователю вводить стандартные команды и инициализировать программы из оболочки. Вот код для демона, который у меня есть до сих пор. Программа logcat запускается и показывает сообщения журнала, но я не могу вводить какие-либо команды в вывод, как кажется, что программа взяла под контроль ввода.

int main ( int argc, char** argv, char** env )
{
    int fd;
    if ((fd = open("/dev/console", O_RDWR)) < 0) {
        fd = open("/dev/null", O_RDWR);
    }
    printf("THIS IS A TESTn");
    dup2(1, fd);
    dup2(2, fd);

    pid_t childpid = fork();

    if(childpid == -1) {
        perror("Failed to fork, logcat not starting");
        return 1;
    }

    if(childpid == 0) {
        //this is the child, exec logcat
        setsid();
        int execReturn = execl("/system/bin/logcat", "logcat", (char *) 0);
    } else {
        //this is the parent do nothing
        close(fd);
        return 0;
    }
    close(fd);
     return 0;
}

спасибо

3 ответов


на 'logcat' команда, похоже, предназначена для разработки Android - это может объяснить нечетное расположение команды.

ключевая операция, которую вы должны исправить, заключается в том, чтобы закрыть текущий стандартный вход (терминал) и открыть /dev/null/ устройства ввода:

close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
    ...error - failed to open /dev/null!

это означает, что ваш демонизированный дочерний процесс ничего не будет читать с терминала.


что я думаю, что вы хотите сделать есть:

  1. запустите программу запуска из командной строки, которая будет иметь стандартный вход, стандартный выход и стандартную ошибку, подключенную к "терминалу".
  2. внутри вашей программы, вы хотите заменить стандартный ввод, так что /dev/null.
  3. вы хотите оставить стандартный вывод в покое-вы хотите logcat для записи на текущий стандартный выход.
  4. вы, вероятно, хотите оставить стандартную ошибку в покое тоже.

в какой-то момент разбирательства вы делаете свой демонизации правильно (заимствуя ссылку из ответа @bstpierre), убедившись, что терминал, к которому вы подключены, не является вашим управляющим терминалом, так что прерывания и зависания, отправленные на терминал, не влияют на ваш демон. Сантехника проще, чем то, что вы настроили - вы должны иметь дело со стандартным входом и оставить стандартный выход и стандартную ошибку без изменений (вместо изменения выходы и оставляя вход неизменным).

теперь вы можете захотеть, чтобы вывод пошел в /dev/console; если это так, то целесообразно пересмотреть код, чтобы открыть /dev/console. Однако возвращаться к /dev/null Если вы не можете открыть /dev/console; ваша программа должна сообщить об ошибке и сбое (потому что нет смысла писать logcat в /dev/null!). Убедитесь, что вы открываете консоль с помощью O_NOCTTY флаг, чтобы он не стал управляющим терминалом для демон.

последний комментарий, который я бы сделал:

  • вы уверены, что хотите, чтобы случайный текст появлялся над вашим терминалом или консолью, когда он используется для других вещей?

мне не очень нравится, когда это происходит.


Читайте также: так 958249


Как демонизировать в Linux [мертвой ссылке]

как демонизировать в Linux [wayback машинный архив выше]

суть на github -- код взят из ссылки выше

резюме:

одна из вещей, с которыми я постоянно сталкиваюсь, - это демоны Linux, которые должным образом не демонизируют себя. Чтобы правильно демонизировать, необходимо выполнить следующие шаги.

  • вызов fork () используется для создания отдельного процесса.
  • вызов setsid () используется для отсоединения процесса от родительского (обычно оболочки).
  • маска файла должна быть сброшена.
  • текущий каталог должен быть изменен на что-то доброкачественное.
  • стандартные файлы (stdin,stdout и stderr) необходимо открыть заново.

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

  • запуск демона, а затем выход из системы приведет к зависанию терминала. Это особенно неприятно с ssh.
  • каталог, из которого был запущен демон, остается заблокированным.
  • ложные выходные данные отображаются в оболочке, из которой был запущен демон.

для этого в glibc есть специальная функция:

#include <unistd.h>

...
/* We are in the parent, yet */
daemon(0,0);
/* Now we are in the child */
...

подробнее здесь http://linux.die.net/man/3/daemon