В чем разница между запуском программы в качестве демона и переходом в фоновый режим с помощью '&'?

46

Каковы практические различия с точки зрения системного администратора при развертывании служб в системе на основе Unix?

user1561108
источник

Ответы:

31

Традиционный способ демонизации - это:

fork()
setsid()
close(0) /* and /dev/null as fd 0, 1 and 2 */
close(1)
close(2)
fork()

Это гарантирует, что процесс больше не находится в той же группе процессов, что и терминал, и, следовательно, не будет уничтожен вместе с ним. Перенаправление ввода-вывода должно сделать вывод не отображаться на терминале.

Деннис Каарсемакер
источник
5
поэтому, если терминал, который порождает фоновый процесс (&), закрыт, фоновый процесс также завершится?
user1561108
9
Процесс получит SIGHUP, когда терминал выйдет, обработчик по умолчанию для этого сигнала должен завершить процесс.
Деннис Каарсемакер
12
Пожалуйста, добавьте &объяснение части к вашему ответу. Это кажется неполным .. если вы проверите оригинальный вопрос.
MTK
1
Это потому, что запуск вещей в фоновом режиме с & не заставляет процесс делать что-то особенное :)
Деннис Каарсемакер
34

Для демона вам нужен процесс, который ни к чему не привязан. По крайней мере, вы хотите, чтобы он находился в своем собственном сеансе, не был подключен к терминалу, не имел файлового дескриптора, унаследованного от родительского элемента, открытого для чего-либо, не имел родительского элемента, который заботится о вас (кроме init) и имеет текущий каталог, /чтобы не предотвратить размонтирование ...

Чтобы отсоединиться от терминала, вы создаете новый сеанс, однако для создания сеанса вы не должны быть лидером группы (или сеанса), поэтому лучше всего раскошелиться на новый процесс. Предполагая, что родитель выходит, это также означает, что у процесса больше не будет родителя, и он будет принят init. Затем закройте все возможные файловые дескрипторы (вы chdir("/")не можете закрыть текущий рабочий каталог, чтобы освободить этот ресурс, как для файловых дескрипторов, поскольку создание /текущих рабочих каталогов по крайней мере не предотвращает размонтирование каталогов).

Поскольку этот процесс является лидером сеанса, существует риск, что, если он когда-либо откроет терминальное устройство, он станет процессом управления этим терминалом. Форкинг второй раз гарантирует, что этого не произойдет.

С другой стороны, & в интерактивных оболочках разветвляется и создает новую группу процессов (чтобы не быть в группе процессов переднего плана терминала), а в неинтерактивных оболочках разветвляет процесс и игнорирует в нем SIGINT. Он не отсоединяется от терминала, не закрывает файловые дескрипторы (хотя некоторые оболочки будут снова открывать стандартный ввод /dev/null) ...

Стефан Шазелас
источник
какая польза от chdir ("/")? закрыть файловый дескриптор?
Тимоти Леунг
@TimothyLeung, см. Редактировать.
Стефан Шазелас
8

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

Чаще всего родительский процесс демона - это процесс init (самый первый процесс, который должен быть запущен в системе Unix), поскольку демон является дочерним процессом этого процесса, это означает, что он не находится под вашим непосредственным контролем как непривилегированный пользователь , С другой стороны, разветвление программы / процесса в фоновом режиме означает, что вы можете в любой момент отозвать его обратно на передний план и / или уничтожить.

Odaym
источник
1
Кроме того, чтобы ответить на вышеуказанную техническую сторону отсоединения процесса от сохранения его в качестве дочернего элемента терминала, вы можете попробовать запустить «nohup firefox &»
Odaym
7

С command &вашим процессом будет убит сигнал SIGHUP, когда родитель умирает.

Однако системные администраторы имеют доступ к некоторым временным решениям.

В системе bash вы можете использовать:

(trap '' HUP; command) &

Это открывает подоболочку, перехватывает HUPсигнал с помощью пустого обработчика и амперсанд / разветвляет его.

Вывод все еще может быть перенаправлен на неправильный tty. Или заблудиться.
Вы можете исправить это &>command.out, 1>output.outили2>errors.out

Вы также можете иметь доступ в большинстве систем к этой nohupкоманде.
nohupзначительно упрощает этот процесс. Это довольно стандартно, но я обнаружил, что во многих дистрибутивах ARM с сервисом busybox его нет. Вы просто пишете:

nohup command &

..и вы сделали. Вывод перенаправляется, IIRC, в nohup.out, но это имя файла может быть изменено с опцией.

Zjr
источник
2
Просто отметим, что с помощью ZSH вы можете отделить command &позднее от оболочки, с disownкоторой затем работает как post-nohup.
математика