Давайте сначала посмотрим, что происходит, если программа запускается из интерактивной оболочки (подключенной к терминалу) без &
(и без какого-либо перенаправления). Итак, давайте предположим, что вы только что набрали foo
:
- Процесс запуска
foo
создан.
- Процесс наследует stdin, stdout и stderr из оболочки. Поэтому он также подключен к тому же терминалу.
- Если оболочка получает a
SIGHUP
, она также отправляет a SIGHUP
процессу (что обычно приводит к завершению процесса).
- В противном случае оболочка ожидает (блокируется), пока процесс не завершится.
Теперь давайте посмотрим, что произойдет, если вы поместите процесс в фоновом режиме, то есть наберите foo &
:
- Процесс запуска
foo
создан.
- Процесс наследует stdout / stderr от оболочки (поэтому он все еще пишет в терминал).
- Процесс в принципе также наследует стандартный ввод, но как только он пытается прочитать из стандартного ввода, он останавливается.
- Он помещен в список фоновых заданий, которыми управляет оболочка, что означает, в частности:
- Он указан с
jobs
и может быть доступен с помощью %n
(где n
номер задания).
- Его можно превратить в задание переднего плана
fg
, и в этом случае он будет продолжаться, как если бы вы его не использовали &
(и если он был остановлен из-за попытки чтения со стандартного ввода, теперь он может приступить к чтению с терминала).
- Если оболочка получила a
SIGHUP
, она также отправляет SIGHUP
процесс. В зависимости от оболочки и, возможно, от параметров, установленных для оболочки, при завершении оболочки она также отправляет SIGHUP
процесс.
Теперь disown
удаляет задание из списка заданий оболочки, поэтому все подпункты выше не применяются (включая процесс, отправляемый SIGHUP
оболочкой). Однако обратите внимание, что он все еще подключен к терминалу, поэтому, если терминал уничтожен (что может произойти, если он был pty, как те, которые созданы xterm
или ssh
, и управляющая программа завершается, закрыв xterm или разорвав соединение SSH ) программа потерпит неудачу, как только она попытается прочитать из стандартного ввода или записать в стандартный вывод.
Что nohup
, с другой стороны, состоит в том, чтобы эффективно отделить процесс от терминала:
- Он закрывает стандартный ввод (программа не сможет прочитать какой-либо ввод, даже если он запущен на переднем плане. Он не остановлен, но получит код ошибки или
EOF
).
- Он перенаправляет стандартный вывод и стандартную ошибку в файл
nohup.out
, поэтому программа не сможет выполнить запись в стандартный вывод в случае сбоя терминала, поэтому все, что записывает процесс, не теряется.
- Это препятствует тому, чтобы процесс получил
SIGHUP
(таким образом, имя).
Обратите внимание, что nohup
это не удаляет процесс из управления заданиями оболочки, а также не переводит его в фоновый режим (но поскольку nohup
задание на переднем плане более или менее бесполезно, вы обычно используете его в фоновом режиме &
). Например, в отличие от с disown
, оболочка все равно сообщит вам, когда задание nohup завершено (конечно, если оболочка не была прервана раньше).
Итак, подведем итог:
&
помещает задание в фоновый режим, то есть блокирует его при попытке прочитать ввод и заставляет оболочку не ждать его завершения.
disown
удаляет процесс из управления заданиями оболочки, но оставляет его подключенным к терминалу. Одним из результатов является то, что оболочка не отправит его SIGHUP
. Очевидно, что его можно применять только к фоновым заданиям, потому что вы не можете ввести его, когда выполняется задание переднего плана.
nohup
отключает процесс от терминала, перенаправляет его вывод nohup.out
и экранирует его SIGHUP
. Одним из эффектов (именование) является то, что процесс не будет получать отправленные SIGHUP
. Он полностью независим от управления заданиями и, в принципе, может использоваться и для заданий на переднем плане (хотя это не очень полезно).