Разница между nohup, disown и &

577

Каковы различия между

$ nohup foo

а также

$ foo &

а также

$ foo & 
$ disown
lesmana
источник
50
Подождите, вы можете отказаться, не указав PID? Большой!
ripper234
34
Есть также то, foo &!что должно быть равносильно тому, чтобы отречься от него с самого начала.
user4514
26
Bash не поддерживает & !.
Джонас Конгслунд
20
foo & disownнемедленно отречься.
Ctrl-Alt-Delor
9
Мне бы очень хотелось увидеть упоминание о нем setsidи о том, как оно связано disownиnohup
YoungFrog

Ответы:

557

Давайте сначала посмотрим, что происходит, если программа запускается из интерактивной оболочки (подключенной к терминалу) без &(и без какого-либо перенаправления). Итак, давайте предположим, что вы только что набрали 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. Он полностью независим от управления заданиями и, в принципе, может использоваться и для заданий на переднем плане (хотя это не очень полезно).
celtschk
источник
8
+1 Спасибо. Что происходит при использовании disown, nohup и & вместе?
Тим
15
Если вы используете все три вместе, процесс выполняется в фоновом режиме, удаляется из управления заданиями оболочки и эффективно отключается от терминала.
celtschk
1
какая разница между disown %1а disown -h %1? Второй будет работать как обычный (но игнорирует сигнал HUP) до выхода из терминала?
schemacs
4
Может быть , стоит в том числе (foo&)подоболочек
jiggunjer
168

Использование &заставляет программу работать в фоновом режиме, так что вы получите новое приглашение оболочки вместо блокировки, пока программа не завершится. nohupи disownв значительной степени не связаны; они подавляют сигналы SIGHUP (зависание), поэтому программа автоматически не отключается при закрытии управляющего терминала. nohupделает это, когда работа начинается впервые. Если у вас нет nohupработы, когда она начинается, вы можете использовать ее disownдля изменения выполняемой работы; без аргументов он изменяет текущую работу, которая была только фоновой

Михаил Мрозек
источник
10
Незначительная разница между nohup и disown: команда disown удалит его из вашего списка вакансий; Нохуп не будет.
Шон Дж. Гофф
191
nohupи disownможно сказать, что оба подавляют SIGHUP, но по-разному. nohupзаставляет программу игнорировать сигнал изначально (программа может изменить это). nohupтакже пытается устроить так, чтобы программа не имела управляющего терминала, чтобы SIGHUPядро не отправляло его при закрытии терминала. disownявляется чисто внутренней оболочкой; это заставляет оболочку не отправлять, SIGHUPкогда это завершается.
Жиль
27
@ Жиль, твой комментарий стоит ответа сам по себе.
Lesmana
5
Просто пояснение к комментарию @ ShawnJ.Goff, касающемуся disownудаления работы из списка вакансий. Если вы не укажете опцию, она удалит ее из списка вакансий. Однако , если вы укажете эту -hопцию, каждая спецификация заданий не будет удалена из таблицы. Вместо этого он делает так, чтобы SIGHUPон не отправлялся на задание, если оболочка получает SIGHUP.
Tacotuesday
4
Просто чтобы прояснить, используя &не дает вам терминал, он отсоединяется stdinот процесса и заставляет его работать в фоновом режиме, но как stdoutи stderrпо - прежнему привязан к текущему TTY. Это означает, что вы можете смешивать текст из разных программ, что может сильно раздражать, если вы делаете gimp &и получаете много ошибок GTK +, пытаясь использовать этот tty для чего-то другого.
Франк
8

Вот мой опыт попытки запустить soffice в фоновом режиме, следуя не завершающей команде (например tail). Для этого примера я буду использовать sleep 100.

&

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Я вижу логи soffice / нажатием Ctrl- Csoffice останавливается

nohup .. &

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Я не вижу журналы soffice / нажатием Ctrl- Csoffice останавливается

& отречься

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

Я вижу логи soffice / нажатием Ctrl- Csoffice останавливается

Сетсид .. &

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Я вижу журналы soffice / нажатием Ctrl- Csoffice НЕ ОСТАНАВЛИВАЕТСЯ

Для экономии места::
nohup setsid ..не показывает журналы / soffice НЕ ОСТАНАВЛИВАЕТСЯ Ctrl-C
nohup с помощью & disownв конце: не показывает журналы / soffice останавливается Ctrl-C

Маринос Ан
источник
2
Хотя я ценю усилия по упоминанию setsid и демонстрации того, что происходит в этой конкретной ситуации, я хотел бы получить более подробный ответ. В частности, разница и сходство каждого решения, как видимого (что происходит, когда закрывается оболочка или терминал, куда идет вывод, ...), так и невидимого (как все делается под капотом и каковы его последствия). Принятый ответ является хорошей основой для этого.
YoungFrog
1
@YoungFrog Я согласен с этим!
Маринос Ан
Для меня с nohup ⟨command⟩ & disownсозданным процесс не останавливается Ctrl+C.
августа
@ k.stm Вы пробовали soffice? sofficeКоманда, кажется, имеет что-то другое. Поэтому я решил добавить его здесь как правило исключения. Например, при использовании:, nohup .. &обычное нажатие Ctrl-cне приводит к остановке команды, но с sofficeней. Я жду, пока кто-нибудь не наступит на это и не объяснит, почему это происходит с soffice :)
Marinos An
@MarinosAn Да, я сделал. Я побежал nohup soffice &и нажал Ctrl+C. Ничего не случилось, как и ожидалось.
18:00