Чому bash ігнорує SIGTERM?


10

Іноді, коли хочеться швидко вийти, я це роблю kill -15 -1. Я помітив, що баш ігнорує SIGTERM.

Цікаво, що обґрунтування такої поведінки баш ?

Не дуже UNIX - ігнорувати SIGTERM без поважних причин, чи не так?

ОНОВЛЕННЯ:

однаковий (не) ефект для всіх:

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

ОНОВЛЕННЯ2:

Від man bash :

Коли bash є інтерактивним, за відсутності пасток він ігнорує SIGTERM

Так це робиться навмисно. Але чому?


Яке вбивство ти використовуєш? /bin/killабо вбудована оболонка? Якщо останнє, я здогадуюсь, що оболонка не вб'є себе власним вбудованим.
тердон

@terdon: Я використовував вбудований, але не думаю, що це причина, щоб не вбивати його самостійно.
Michał Šrajer

1
Якщо ви хочете швидко вийти, скористайтеся Ctrl + d
YoMismo

1
@YoMismo: "вихід із X сесії"
Michał Šrajer

2
@ MichałŠrajer: Ctrl-Alt-Backspace робить це для мене на Xorg ... можливо, вам доведеться ввімкнути це в xorg.conf.
Ласло Валько

Відповіді:


10

По-перше, це не характерно для bash. ATT ksh, dash та zsh поводяться однаково: вони ігнорують SIGTERM та SIGQUIT під час випуску командного рядка; що стосується mksh, він також не виходить, але трактує їх як SIGINT.

Як посібник ksh, так і посібник bash виправдовують ігнорування SIGTERM у цих термінах:

щоб kill 0не вбивати інтерактивну оболонку

kill 0вбиває всі процеси в групі процесів, в якій знаходиться оболонка. У двох словах, група процесів складається з усіх процесів, що працюють на передньому плані на терміналі, або всіх процесів у фоновому режимі або призупиненому завданні.

Точніше, це відбувається в сучасних оболонках з контролем роботи . У таких оболонках kill 0це не буде корисним, оскільки оболонка знаходиться у власній групі процесів. Старіші оболонки (або сучасні оболонки після set +m) не створювали групи процесів для фонових команд. Таким чином, ви можете використовувати команду, kill 0щоб знищити всі фонові команди, не виходячи з системи kill 0.

Однак є й інші подібні ситуації, коли зробити захисну оболонку корисною. Розглянемо випадок, коли у вас є процеси підключення терміналу, і ви хочете вбити їх, не виходячи з системи. У багатьох системах є такий інструмент, pkillякий дозволяє вбивати процеси, що працюють на терміналі. Ви можете запустити pkill -t $TTYабо pkill -QUIT -t $TTYвбити всі процеси, що працюють на поточному терміналі, крім оболонки, яка ігнорує сигнал.

Оболонка зазвичай відмирає або коли користувач виходить з неї (з командою типу exitабо logout), або коли її термінал сигналізує про кінець вводу (користувач може викликати це натисканням Ctrl+ D) або зовсім відходить. В останньому випадку оболонка приймає сигнал SIGHUP, і він не ігнорує цей.

Для вашого випадку виходу з сеансу X kill -15 -1це зробить, оскільки він вбиває емулятор терміналу, через що оболонка отримує SIGHUP. Насправді достатньо вбити X-сервер, але для цього потрібно знайти його ідентифікатор процесу. Якщо ви хочете, щоб ця сама команда працювала над текстовим сеансом, ви можете використовувати kill -15 -1; exit. Це досить небезпечна команда все одно мати під рукою.

¹ Це, мабуть, не згадується в посібниках з оболонками; це особливість базового системного виклику. Він прямо згадується в специфікації POSIX .
² Сьогодні, щоб зробити це, запустіть, jobs -lщоб переглянути список завдань із їх ідентифікаційною групою процесорів, а потім kill -123 -456 …вбити групи процесів.


5

Це може відповісти на ваше запитання:

Коли Bash є інтерактивним, за відсутності пасток він ігнорує SIGTERM (так, що "kill 0" не вбиває інтерактивну оболонку), а SIGINT вловлюється та обробляється (щоб вбудований режим очікування був переривним). Коли Bash отримує SIGINT, він виривається з усіх циклів виконання. У всіх випадках Баш ігнорує SIGQUIT. Якщо діє контроль за роботою (див. Контроль роботи), Bash ігнорує SIGTTIN, SIGTTOU та SIGTSTP.

Не вбудовані команди, запущені Bash, мають обробники сигналів, встановлені на значення, успадковані оболонкою від свого батьківського. Якщо контроль за роботою не діє, асинхронні команди ігнорують SIGINT та SIGQUIT на додаток до цих успадкованих обробників. Команди, що виконуються в результаті заміни команд, ігнорують сигнали управління роботою клавіатури SIGTTIN, SIGTTOU та SIGTSTP.

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

Якщо параметр оболонки huponexit був встановлений за допомогою shopt (див. Shopt Builtin), Bash надсилає SIGHUP на всі завдання, коли виходить інтерактивна оболонка входу.

Якщо Bash чекає завершення команди і отримує сигнал, для якого встановлено пастку, пастка не буде виконана, поки команда не завершиться. Коли Bash чекає асинхронної команди за допомогою вбудованого очікування, прийом сигналу, для якого встановлена ​​пастка, призведе до негайного повернення вбудованого очікування зі статусом виходу більше 128, одразу після чого пастка виконується.

ДЖЕРЕЛ : посібник GNU Bash


Я цитував це у своєму оновленні2. Людина заявляє, що Баш так робить, але не пояснює, чому таке рішення. Залишається питання - чому?
Michał Šrajer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.