Я пытаюсь сделать что-то немного странное здесь. Я должен запустить процесс, logcat, от deamon, который будет работать в фоновом режиме и печатать к терминалу без того, чтобы брать под свой контроль stdin. Это для входа, таким образом, идеально logcat распечатает сообщения журнала, все еще позволяя пользователю ввести стандартные команды и инициализировать программы от оболочки. Вот код для демона, которого я имею до сих пор. Программа, logcat, запускает и показывает сообщения журнала, но я не могу ввести команды в stdin, поскольку кажется, что программа взяла под свой контроль stdin.
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 TEST\n");
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;
}
Спасибо
Команда 'logcat' , похоже, предназначена для разработки под Android - это может объяснить странное расположение команды.
Ключевая операция, которую вы должны исправить, - это убедиться, что вы закрыли текущий стандартный ввод (терминал) и открыли / dev / null /
для устройства ввода:
close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
...error - failed to open /dev/null!
Это означает, что ваша демонизированная дочерний процесс не будет ничего читать с терминала.
Я думаю, вы хотите сделать следующее:
/ dev / null
. logcat
записывал в текущий стандартный вывод. В какой-то момент процедуры вы правильно выполняете демонизацию (заимствуя ссылку из ответа @bstpierre), убедившись, что терминал, к которому вы подключены, не является вашим управляющим терминалом, чтобы прерывания и сообщения, отправленные на терминал, не влияют на работу вашего демона. Сантехника проще, чем то, что вы настроили - вы должны иметь дело со стандартным вводом и оставить стандартный вывод и стандартную ошибку без изменений (вместо того, чтобы изменять выводы и оставлять ввод без изменений).
Теперь вы можете захотеть, чтобы вывод шел на / dev / console
; если это так, то разумно изменить код, чтобы открыть / dev / console
.Однако нецелесообразно возвращаться к / dev / null
, если вы не можете открыть / dev / console
; ваша программа должна сообщить об ошибке и выйти из строя (потому что нет смысла в том, чтобы logcat записывал в / dev / null
!). Убедитесь, что вы открыли консоль с флагом O_NOCTTY
, чтобы она не стала управляющим терминалом для демона.
Последний комментарий, который я хотел бы сделать:
Мне не очень нравится, когда это происходит .
См. Также: SO 958249
Как демонизировать в Linux [мертвая ссылка]
Как демонизировать в Linux [машинный архив обратного пути]
суть на github - код взят из ссылки выше
Краткое изложение:
Одна из вещей, с которой я постоянно сталкиваюсь, - это демоны Linux, которые не демонизируют себя должным образом. Чтобы правильно демонизировать, необходимо выполнить следующие шаги.
- Вызов fork () используется для создания отдельного процесса.
- Вызов setsid () используется для отделения процесса от родительского (обычно оболочки).
- Необходимо сбросить маску файла.
- Текущий каталог следует изменить на что-нибудь безопасное.
- Необходимо повторно открыть стандартные файлы (stdin, stdout и stderr).
Невыполнение любого из этих шагов приведет к некорректному поведению процесса-демона. Типичные симптомы следующие.
- Запуск демона и последующий выход из системы приведет к зависанию терминала. Это особенно неприятно с ssh.
- Каталог, из которого был запущен демон, остается заблокированным.
- В оболочке, из которой был запущен демон, появляется ложный вывод.