Работают ли `disown -h` и` nohup` одинаково?

18

disown

  • заставляет оболочку не посылать SIGHUP на свое отрешенное задание, когда оболочка завершается, и

  • удаляет оторванное задание из управления заданиями оболочки.

Является ли первое результатом второго? Другими словами, если процесс, запущенный из оболочки, каким-либо образом удален из управления заданиями оболочки, не будет ли оболочка отправлять SIGHUP процессу, когда оболочка завершается?

disown -h все еще держит процесс под контролем работы оболочки. Означает ли это, что disown -hпроцесс все еще получает SIGHUP, отправленный из оболочки, но настраивает действие SIGHUP для процесса, чтобы он "игнорировался"? Это звучит похоже на nohup.

$ sleep 123 & disown -h
[1] 26103
$ jobs
[1]+  Running                 sleep 123 &
$ fg 1
sleep 123
$ ^Z
[1]+  Stopped                 sleep 125
$ bg 1
[1]+ sleep 123 &
$ exit

$ ps aux | grep sleep
t        26103  0.0  0.0  14584   824 ?        S    15:19   0:00 sleep 123

Делать disown -hи nohupработать эффективно одинаково, если не учитывать их разницу в использовании терминала?

Благодарю.

Тим
источник
Другое различие, которое здесь не обсуждается, заключается в том, что если вы не используете его nohup, вам нужно перенаправить stdin / stdout / stderr из TTY (если ваша исходная оболочка подключена к нему) самостоятельно. (OTOH, я на самом деле считаю, что это лучшая практика, чем полагаться на вопиющее жестко заданное значение по умолчанию, как ./nohup.out).
Чарльз Даффи

Ответы:

21

nohupи disown -hне совсем то же самое.

При disownэтом процесс удаляется из списка заданий в текущей интерактивной оболочке. Запуск jobsпосле запуска фонового процесса и его запуск disownне будут отображать этот процесс как задание в оболочке. Отказавшееся задание не получит HUPот оболочки при выходе (но см. Примечание в конце).

При disown -hэтом задание не удаляется из списка заданий, но оболочка не будет отправлять ему HUPсигнал, если оно завершится (но см. Примечание в конце).

nohupУтилита игнорирует HUPсигнал и запускает данную утилиту. Утилита наследует маску сигнала nohupи поэтому также игнорирует HUPсигнал. Когда оболочка завершается, этот процесс остается дочерним процессом nohupnohupповторно связан с ним init).

Разница в том, что процесс начался с nohupигнорирования HUPнезависимо от того, кто посылает сигнал. В отрекся процессы просто не послал на HUPсигнал оболочкой , но по- прежнему может быть послан сигнал , например , от kill -s HUP <pid>и не будет игнорировать это.

Обратите внимание, что HUPотправляется на задания оболочки только если

  • оболочка является оболочкой входа в систему, и huponexitопция оболочки установлена, или
  • сама оболочка получает HUPсигнал.

Соответствующие биты из bashруководства (мой акцент):

СИГНАЛЫ

[...]

По умолчанию оболочка завершает работу при полученииSIGHUP . Перед выходом интерактивная оболочка отправляет SIGHUPвсе задания, запущенные или остановленные. Остановленные работы отправляются, SIGCONTчтобы гарантировать, что они получают SIGHUP. Чтобы оболочка не отправляла сигнал на конкретное задание, его следует удалить из таблицы заданий с помощью disownвстроенной функции (см. SHELL BUILTIN COMMANDSНиже) или пометить, чтобы он не принимался SIGHUP с помощью disown -h.

Если параметр huponexitоболочки был установлен с помощью shopt, bashотправляет a SIGHUPвсем заданиям при выходе из интерактивной оболочки входа.

disown [-ar] [-h] [jobspec ... | pid ... ]

Без опций удалите каждую jobspecиз таблицы активных заданий. [...] Если -hуказан параметр, каждый из jobspecних не удаляется из таблицы, а помечается, чтобы SIGHUPне отправляться на задание, если оболочка получает aSIGHUP . [...]

Связанный:

Кусалананда
источник
Я получаю bash: disown: nohup: no such jobи то же самое для sleepи 5от disown nohup sleep 5 &. Что вы имели в виду под этой второй командой из последнего предложения?
Руслан
@Ruslan Да, я &там скучаю (и порядок nohupи disownтоже был неправильным). Благодарю. Буду обновлять сейчас.
Кусалананда
@Tim Извините за чрезмерное редактирование ответа. Потребовалось время, чтобы обдумать это. Я сделал сейчас.
Кусалананда
Благодарю. disownделает оболочку не отправленной SIGHUP дочернему элементу, удаляя дочерний элемент из списка заданий оболочки. Как disown -hдобиться того же?
Тим
4

Они разные:

  • disown удаляет задание из таблицы активных заданий. Затем продолжается с текущей работой. С -h процесс НЕ отправляется SIGHUP. Вместо этого его оставляют умирать с оболочкой, в которой он находится, когда он получает SIGHUP.

  • nohup игнорирует HUP. Тогда все, что было бы передано в терминал при закрытии процесса, вместо этого отправляется в файл nohup.out.

    nohup определяется POSIX, а disown - нет.

Майкл Прокопец
источник
Что вы имеете в виду, «умереть с оболочкой, которая содержит его»? Убийство родительского процесса само по себе не убивает ребенка. Программы, терминалы которых закрыты, обычно умирают из-за сбоев, связанных с попытками взаимодействия с дескриптором файла, прикрепленным к PTY терминала, но если stdin / stdout / stderr перенаправляется в другое место, этого не произойдет.
Чарльз Даффи