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