Чому мій процес все ще працює після виходу з системи?


10

Після входу через систему sshя набираю цю команду bash:

sleep 50000000000000 &

Тоді я kill -9цей sleepпроцес в батьківському процесі (тобто bash). Потім вікно терміналу одночасно відключається.

Коли я знову входжу в систему, я виявляю, що sleepпроцес все ще живий.

Запитання : Чому sleepпроцес може виживати, коли я вийшов із системи та термінал закритий? На мій погляд, nohupпід час виходу все, крім демонів і програм, буде вбито. Якщо sleepможна вижити таким чином, чи означає це, що я можу використовувати цей метод замість nohupкоманди?


3
&буде перенаправляти процес на другий план (наприклад, демон) і продовжує працювати щонайбільше, хоча ви вийшли з системи.
Айзуддін Залі

Відповіді:


6

Tl; dr:

Чому sleepпроцес може вижити, коли я виходжу з системи та термінал закритий? На мій погляд, nohupпід час виходу все, крім демонів і програм, буде вбито. Якщо sleepможна вижити таким чином, чи означає це, що я можу використовувати цей метод замість nohupкоманди?

Якщо bashекземпляр, породжений яким, sshне huponexitвстановив параметр, жоден спосіб не буде припинений після виходу / виходу, і коли huponexitпараметр встановлений, використання kill -9на оболонці не є хорошою альтернативою для використання nohupв дочірніх процесах оболонки; nohupна дочірніх процесах оболонки все одно захищатимуть їх від SIGHUPs, що не надходять від оболонки, і навіть коли це не важливо nohup, все-таки слід віддати перевагу, оскільки це дозволяє виграшно закінчити оболонку.


В bashє опція називається huponexit, що якщо набір зробить bashSIGHUP своїх дітей при виході / виході з системи;

В інтерактивних екземплярах, які не входять у систему, bash наприклад, в bashекземплярі, породженому gnome-terminalцією опцією, ця опція ігнорується; незалежно від того huponexit, встановлено чи не встановлено, bashдіти ніколи не будуть ВИДАЛЕНИМИ bashпісля виходу;

У випадках інтерактивного входу, bash наприклад, у bashвипадку, породженому екземпляром ssh, ця опція не ігнорується (однак вона за замовчуванням не встановлена); якщо huponexitвстановлено, bashдіти будуть ВИГОТОВЛЕНІ bashпри виході / виході; якщо huponexitце не встановлено, bashдіти не будуть ВИБІРЮТЬСЯ bashпісля виходу / виходу;

Отже, як правило, вихід / вихід із інтерактивного bashекземпляра входу , якщо не встановлено huponexitпараметр, оболонка SIGHUP не зробить її дочірніми, а вихід / вихід із інтерактивного bashекземпляра, що не входить , не зробить оболонку SIGHUP її дітьми незалежно;

Це, однак, не має значення в даному випадку: використання kill -9 sleepвиживуть незалежно, тому що вбиває його батьківський процес ( bash) не залишить шансів для останнього , щоб зробити що - небудь до першого (тобто, наприклад, якщо поточний bashекземпляр був Ввійти bashекземпляр і huponexitопція була встановлена, щоб ЗНАЧИТИ її).

Додаючи до цього, на відміну від інших сигналів (на зразок сигналу SIGHUP, що надсилається bash), сигнал SIGKILL ніколи не передається дочірнім процесам процесу, отже sleep, навіть не вбивається;

nohupзапускає процес, несприйнятливий до сигналів SIGHUP, який є чимось іншим; це запобіжить зависанню процесу після прийому сигналу SIGHUP, який у цьому випадку може бути отриманий інтерактивним bashекземпляром входу у випадку, якщо huponexitпараметр був встановлений і оболонка вийшла з ладу; тому технічно використання nohupдля запуску процесу в інтерактивному bashекземплярі входу з huponexitвимкненою опцією запобігає зависанню процесу при отриманні сигналу SIGHUP, але вихід із / виходу з оболонки не буде ВИБІР нею незалежно;

Однак у цілому, коли nohupце потрібно для запобігання надходженню сигналів SIGHUP з батьківської оболонки, немає жодної причини віддавати перевагу kill -9методу батьківського типу nohupдочірньому методу; натомість має бути навпаки.

Вбивство батьків за допомогою kill -9методу не залишає шансу батькові граціозно вийти, а запуск дитини за допомогою nohupметоду дозволяє батькові припинятися за допомогою інших сигналів, таких як SIGHUP (зробити приклад, який має сенс у контексті дитини почали використовувати nohup), які дозволяють їй вишукано вийти.


Іншими словами, якщо у мене є сценарій, розміщений у фоновому режимі, він все одно буде запущений, навіть якщо я вбиваю батьківський процес, наприклад, моя оболонка правильно? який би був спосіб вбити цей сценарій?
Сергій Колодяжний

@Serg Якщо у вас є PID, просто вбийте PID; якщо ви не зберігали PID, але ви можете ідентифікувати процес за його іменем, ps -e | grep processслід перелічити процес разом із PID (а ще краще, pgrep -x processякщо ви впевнені, що відповідають цьому одному процесу, а не непотрібні речі); Проблема полягає в тому, що коли ви вбиваєте процес з kill -9його дітьми, які перебувають у власності upstart, отже, їхній оригінальний PPID втрачається, а їх PPID змінюється на PID початкового рівня, що робить їх невпізнанними (AFAIK), але для їх імені або PID
kos

@kos За яких умов nohupне вдасться запобігти зависанню процесу після отримання сигналу SIGHUP від ​​батьківського процесу? Я намагаюся запустити процес у фоновому режимі (в терміналі оболонки PuTTY SSH) nohup <command> <arg> &. Коли я вийду, натиснувши кнопку PuTTY X, фоновий процес негайно припиниться. Коли я вийду з системи, ввівши exitтермінал оболонки PuTTY SSH, процес продовжить працювати у фоновому режимі.
userpal

3

bashза замовчуванням не надсилає сигнал HUP дочірнім процесам при виході . Більш докладно (спасибі @kos), він ніколи не робить це для оболонок без входу .

Ви можете налаштувати bash, щоб зробити це для оболонок входу, якщо встановити параметр huponexit. У терміналі виконайте:

[romano:~] % bash -l

(для цього запустіть нову оболонку "входу")

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Тепер перевірте sleepпроцес:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... не працює: він отримав сигнал HUP і вийшов із запиту.


@kos --- так, ви маєте рацію , але ... так чому , якщо я sleep 1000 & ; exitв sleepвиживає? Зверніть увагу , що якщо я процес він буде виходити. І навіть якщо встановити, виживає. Плутати ... (Я спробую краще зрозуміти та змінити asnwer, інакше я його видалю). kill -HUPsleephuponexitsleep
Рмано

2

Якщо sleepможна вижити таким чином, якщо це означає, що я можу використовувати цей метод замість nohupкоманди?

kill -9насправді не той шлях, яким треба йти. Це як стріляти з пістолетом у телевізор, щоб вимкнути його. Крім комедійної складової, переваги немає. Процеси не можуть наздогнати або проігнорувати SIGKILL. Якщо ви не даєте процесу закінчити те, що він робить і очистити, він може залишити пошкоджені файли (або інший стан) навколо і не зможе запуститися заново. kill -9є останньою надією, коли більше нічого не працює.


Чому процес сну може вижити, коли я виходжу з системи, а термінал закритий. На мою думку, при виході з системи все, крім демона та програми Nohup, буде вбито.

Що у вашому випадку відбувається:

Батьківський процес sleep- це поточно запущена bashоболонка. Коли ви, kill -9що баш, процес bash не має шансу надіслати SIGHUPбудь-який з його дочірніх процесів, тому що SIGKILL(який надсилається kill -9) не піддається лову. Процес сну триває. сон тепер став сирітським процесом .

Процес init (PID 1) робить механізм, який називається переоформленням. Це означає, що процес init тепер стає батьком цього сиротного процесу. init - виняток, процеси можуть стати його дочірніми, оскільки він збирає процеси, які втратили початковий батьківський процес. Btw: Демон (як sshd) робить це, коли "йде у фоновому режимі".

Якби цього не сталося, осиротілий процес згодом (коли закінчиться) стане процесом зомбі. Це те, що відбувається, коли waitpid()не викликається (відповідальність батьківського процесу, який не може бути заповнений, коли цей процес був убитий). init дзвонить waitpid()у певний інтервал, щоб уникнути дітей зомбі.


Процес виживає навіть з ввічливими сигналами на кшталт TERMабоHUP
heemayl

@heemayl HUP залежить від конфігурації оболонок: huponext. І термін чекатиме, поки сон закінчиться. У випадку, коли команда сну OPs пройшла би тисячі років =)
хаос

1

&Запускає процес у фоновому режимі. Якщо ви введете текст ps -ef, ви побачите, що ідентифікатор батьківського процесу вашого сну є вашим ударом. Потім вийдіть із системи та увійдіть знову. Процес залишиться запущеним після виходу з системи. Після входу вдруге ви ps -efзнову запускаєтесь . Ви побачите, що тепер батьків вашого процесу сну буде оброблятися з id "1". Тобто це init, батьківщина всіх процесів.


0

Використання &призведе до запуску програми як фону. Щоб побачити програму у фоновому режимі, використовуйте bgкоманду та змусити її знову працювати як передній план, запустіть fg.

Так, існує багато способів утримати роботу програми навіть у головному терміналі.


Дякую. сторінка чоловіка bash трохи заплутана. Він сказав , що: «Перед виходом, інтерактивна оболонка повторно відправляє SIGHUP всіх завдань, працює або зупинений.» Але насправді, оболонка тільки послати SIGHUP в forground робочих місць. фонові процеси не мають шансів отримати сигнал SIGHUP (якщо не змінити параметри оболонки 'huponexit')
tom_cat

@kos, можливо, ти маєш рацію. Я роблю вищезазначений висновок із цього поста: stackoverflow.com/questions/4298741/… зараз я ще більше плутаюсь.
tom_cat

@tom_cat Назад до цього знову, думаючи про це двічі: там просто немає випадку , в якому оболонка може вийти з процесом переднього плану роботи, він може бути SIGHUPped або що - то, але це не вихід . Це правильно, це стосується лише фонових процесів, оскільки навпаки не мало б сенсу. Однак з подальших досліджень майте на увазі також, що huponexitпрацює тільки на оболонках входу, таких як оболонка, отримана через ssh(а не, скажімо, в оболонці, отриманій через gnome-terminal)
kos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.