Давайте сначала посмотрим, что происходит, если программа запускается из интерактивной оболочки (подключенной к терминалу) без &(и без какого-либо перенаправления). Итак, давайте предположим, что вы только что набрали 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. Он полностью независим от управления заданиями и, в принципе, может использоваться и для заданий на переднем плане (хотя это не очень полезно).