Чи фонові процеси отримують SIGHUP під час виходу з системи?


21

Це продовження цього питання .

Я провів ще кілька тестів; виглядає, що це насправді не має значення, чи це робиться на фізичній консолі або через SSH, і це не відбувається лише з SCP; Я також тестував його cat /dev/zero > /dev/null. Поведінка точно така ж:

  • Почніть процес у фоновому режимі, використовуючи &(або поставте його у фоновий режим після його використання CTRL-Zта bg); це робиться без використанняnohup .
  • Вийдіть із системи.
  • Увійдіть знову.
  • Цей процес все ще існує, протікає щасливо, і зараз він є безпосередньою дитиною init.

Я можу підтвердити, що і SCP, і CAT припиняються негайно, якщо надсилаються SIGHUP; Я перевірив це, використовуючи kill -HUP.

Таким чином, це дійсно схоже на те, що SIGHUP не надсилається під час виходу з системи, принаймні до фонових процесів (неможливо протестувати передній план з очевидних причин).

Це сталося зі мною спочатку з сервісною консоллю VMware ESX 3.5 (яка базується на RedHat), але мені вдалося її повторити саме на CentOS 5.4.

Знову питання: чи не слід SIGHUP надсилати процесам, навіть якщо вони працюють у фоновому режимі, після виходу з системи? Чому цього не відбувається?


Редагувати

Я перевірив strace, як відповів Кайл.
Як я очікував, процес не отримує жодного сигналу при виході з оболонки, де він був запущений. Це відбувається як при використанні консолі сервера, так і через SSH.


Використовуючи Bash на CentOS 7.1, простий цикл скриптів оболонки отримає SIGHUP, якщо він залишиться на передньому плані, але термінал убитий; напруга з іншого терміналу показує: --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=10676, si_uid=3000090} --- rt_sigreturn() = -1 EINTR (Interrupted system call) rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
Майк S

Так буде фоновий сценарій. Зауважте, що термінал закритий, коли цикл чекає сну. Снаряд НЕ вийшов:--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=13944, si_uid=3000090} --- +++ killed by SIGHUP +++
Майк S

Дивіться мою відповідь на тести. Цікаво, що я не бачив змін у поведінці через huponexit.
Майк S

Відповіді:


26

Відповідь знайдена

Для BASH це залежить від параметра huponexitоболонки, який можна переглянути та / або встановити за допомогою вбудованої shoptкоманди.

Схоже, що ці параметри вимкнено за замовчуванням, принаймні для систем на базі RedHat.

Більше інформації на чоловічій сторінці BASH :

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

Якщо параметр оболонки huponexit був встановлений з shopt, bash надсилає SIGHUP на всі завдання, коли виходить інтерактивна оболонка входу.


4
Перевірено. Коли я виконував "вихід", "вихід" або CTL-D, дочірня програма (робота) не отримала б зітхання (як root, так і користувач reg). Однак коли я "убив -HUP $$", щоб убити поточний екземпляр баш, дочірні процеси DID отримали зітхання. Потім я встановив huponexit, і дочірній процес отримав SIGHUP після виходу.
CarpeNoctem

3

Він буде надісланий SIGHUP в моїх тестах:

Оболонка1:

[kbrandt@kbrandt-opadmin: ~] ssh localhost
[kbrandt@kbrandt-opadmin: ~] perl -e sleep & 
[1] 1121
[kbrandt@kbrandt-opadmin: ~] ps
  PID TTY          TIME CMD
 1034 pts/46   00:00:00 zsh
 1121 pts/46   00:00:00 perl
 1123 pts/46   00:00:00 ps

Shell2:

strace -e trace=signal -p1121

Shell1 знову:

[kbrandt@kbrandt-opadmin: ~] exit
zsh: you have running jobs.
[kbrandt@kbrandt-opadmin: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Знову Shell2 :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Чому він все ще працює ?:
Розширене програмування в середовищі Unix Stevens розглядає це у розділі 9.10: Групи сиріт-процесів. Найбільш релевантний розділ:

Оскільки група процесів осиротіла, коли батьків закінчується, POSIX.1 вимагає, щоб кожен процес у новоствореній групі процесів, яка зупинена (як і наша дитина), надсилав сигнал відключення (SIGHUP) з подальшим сигналом продовження (SIGCONT ).

Це спричиняє продовження дитини після обробки сигналу відключення. Дія за замовчуванням для сигналу відключення - це припинення процесу, тому ми маємо надати обробник сигналу, щоб зафіксувати сигнал. Тому ми очікуємо, що printf у функції sig_hup з'явиться перед printf у функції pr_ids.


Але ви явно надіслали сюди SIGHUP; Я говорив про те, що відбувається, коли ви виходите з оболонки, де ви розпочали процес.
Массімо,

Такі самі результати, коли я набираю вихід, хоча отримую попередження про завдання, але потім знову набираю вихід. Я тестував це на ZSH.
Кайл Брандт

Я використовую BASH, і це, мабуть, залежить від оболонки. Але BASH повинен надсилати SIGHUP дочірнім процесам під час виходу з системи ...
Массімо,

Bash надсилає SIGCONT, мабуть, якщо завдання припинено, але я підтверджую, що він нічого не надсилає, якщо завдання не було зупинено.
Кайл Брандт

Використовуючи Bash на CentOS 7.1, я отримую SIGTERM, відправлений моєму процесу, зупиняється в іншому вікні: 1.) Запустіть простий скрипт оболонки (петля з відлунням і сном), 2.) Control-Z it, 3) розподіліть процес у інше вікно, 4) вийти з вихідного терміналу. Він скаржиться на те, що у мене працює робота, то після виходу з моїх страйк-шоу: $ strace -e signal -p1705 Process 1705 attached --- stopped by SIGTSTP --- --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=791, si_uid=3000090} --- +++ killed by SIGTERM +++ Дивно, точно не узгоджується з розділом, цитованим зі Стівенса.
Майк S

2

Я провів кілька тестів за допомогою CentOS 7.1 та bash. Зверніть увагу , це означає , що huponexitце offза замовчуванням, і був виключений для більшості моїх тестів.

Вам потрібно, nohupколи ви починаєте роботу в терміналі, тому що якщо закрити цей термінал, не виходячи з оболонки чисто , термінал надсилає bash сигнал SIGHUP до оболонки, який потім надсилає його всім дітям. Якщо ви виходите з оболонки чисто - значить, завдання вже повинно бути у фоновому режимі, щоб ви могли набрати exitабо натиснути Control-D у командному рядку - жодні сигнали не надсилаються до фонового завдання з bash.

Тест:

Термінал 1

$ echo $$
16779

Термінал 2

$ strace -e signal -p16779
Process 16779 attached

(закрити термінал 1, видно в терміналі 2):

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP)                     = 0
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++

Робота doit.sh:

#!/bin/bash

imhupped() {
        echo "HUP" >> /tmp/outfile
}

trap imhupped SIGHUP

for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done

Почніть його у фоновому режимі в Терміналі 1:

Термінал 1

$ ./doit.sh &
[1] 22954

Прострочіть його в терміналі 2; закрийте клему 1 через пару петель:

Термінал 2

$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
...

Вихід у терміналі 3:

Термінал 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Однак якщо ви виходите bash, він просто виходить, не надсилаючи дитині жодного сигналу. Термінал вийде, тому що у нього більше немає дитини, але, звичайно, немає кого в HUP, оскільки дитяча оболонка вже відсутня. І SIGINT, SIG_BLOCKі SIG_SETMASKви бачите нижче, завдяки sleepоболонці.

Термінал 1

$ ./doit.sh &
26275

Термінал 2

$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0


(..."exit" is typed in bash, notice no new signals sent...)


rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0

Термінал 3, вихід

out 1
out 2
out 3
out 4
out 5
out 6

Цікаво, що я приступив huponexitдо роботи shopt -s huponexit; shopt(останній пройшов огляд), потім провів останній тест, і знову баш не послав жодного сигналу до фонового процесу . Навіть MORE Interstingly, як ми вже бачили Баш зробив послати сигнал на фоновий процес після того, як він отримав його від терміналу , який був закритий в його особі. Схоже, не huponexitмав жодного стосунку до того чи іншого шляху.

Я сподіваюся, що це видалить будь-яку таємницю або плутанину щодо принаймні башти, а також коли і як передається сигнал HUP. Принаймні, мої тести були для мене повністю відтворюваними. Мені було б цікаво дізнатись, чи є інші налаштування, які можуть впливати на поведінку Баша.

І, як завжди, YSMV (Your Shell May Vary).

Додаток 1

Коли я запускаю оболонку як exec /bin/sh, потім запускаю скрипт як /bin/sh ./doit.sh &, а потім чисто виходьте з оболонки, сигнали не надсилаються до фонового завдання, і він продовжує працювати до завершення.

Додаток 2

Коли я запускаю оболонку як exec /bin/csh, потім запускаю скрипт як /bin/sh ./doit.sh &, а потім чисто виходьте з оболонки, сигнали не надсилаються до фонового завдання, і він продовжує працювати до завершення.


0

Я використовую csh та фонові процеси, які продовжують працювати під час входу в систему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.