Процеси можуть вибрати:
- ігнорувати сигнал SIGINT, який зазвичай надсилається після натискання Ctrl-C(як
trap '' INTу оболонці), або мати власного обробника для нього, який вирішує не припиняти (або не вдається припинити своєчасно).
- скажіть термінальному пристрою, що символ, який викликає надсилання SIGINT на завдання переднього плану, є чимось іншим (наприклад,
stty int '^K'в оболонці)
- скажіть термінальному пристрою не надсилати жодного сигналу (наприклад,
stty -isigв оболонці).
Або вони можуть бути безперебійними, як, наприклад, в середині системного дзвінка, який неможливо перервати.
У Linux (із відносно недавнім ядром) ви можете дізнатися, чи процес ігнорує та / або обробляє SIGINT, переглянувши вихід
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT - 2. Другий біт SigIgn вище - 1, що означає, що SIGINT ігнорується.
Ви можете автоматизувати це за допомогою:
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
Щоб перевірити, що є поточним intrсимволом або якщо isigвін увімкнено для даного терміналу:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(вище intrсимволу є ^C(символ, який зазвичай надсилається вашим терміналом (емулятором), коли натискання CTRL-Cта введення сигналів не вимкнено).
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
( intrсимвол є ^Kі isigвимкнено для /dev/pts/1).
Для повноти є два інші способи, які можуть зробити щось, щоб припинити отримання SIGINT, хоча це зазвичай не те, що ви бачите.
Після Ctrl+Cцього сигнал SIGINT надсилається всім процесам в передній план групи процесів терміналу . Зазвичай оболонка розміщує процеси в групах процесів (відображаються на завданнях оболонок ) і повідомляє кінцевому пристрою, який є на передньому плані .
Тепер процес міг:
Залиште його процесну групу. Якщо він переміститься до іншої групи процесів (будь-якої групи процесів, окрім тієї, що є передньою формою ), вона більше не буде отримувати ЗНАК Ctrl-C(ні інші сигнали, пов'язані з клавіатурою, такі як SIGTSTP, SIGQUIT). Однак він може бути призупинений, якщо він спробує прочитати (можливо, також добре, залежно від налаштувань термінального пристрою) з термінального пристрою (як це роблять фонові процеси).
Як приклад:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
не вдалося перервати Ctrl-C. Вище perlнамагатиметься приєднатися до групи процесів, ідентифікатор якої збігається з ідентифікатором батьківського процесу. Загалом, немає гарантії, що існує така група процесів з цим ідентифікатором. Але тут, у випадку, коли ця perlкоманда запускається самостійно під час запиту інтерактивної оболонки, ppid буде процесом оболонки, і оболонка, як правило, запускається у власній групі процесів.
Якщо команда вже не є лідером групи процесів (керівником цієї передньої групи процесу), то запуск нової групи процесів матиме такий же ефект.
Наприклад, залежно від оболонки,
$ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
PID PGID SID TTY TIME CMD
21435 21435 21435 pts/12 00:00:00 zsh
21441 21441 21435 pts/12 00:00:00 ps
21442 21441 21435 pts/12 00:00:00 perl
матиме такий же ефект. psі perlзапускаються в групі процесу переднього плану, але на більшості оболонок psбуде лідером цієї групи (як видно з psрезультатів вище, де pgid обох psі perlє pid ps), тому perlможе запустити власну групу процесу.
Або це може змінити групу процесу переднього плану. В основному, скажіть пристрою tty, щоб надсилати SIGINT до якоїсь іншої групи процесівCtrl+C
perl -MPOSIX -e 'tcsetpgrp (0, getppid) або die $ !; спати 5 '
Там perlзалишається в тій самій групі процесів, але натомість повідомляє термінальному пристрою, що група процесу переднього плану - це та сама, ідентифікатор якої збігається з ідентифікатором батьківського процесу (див. Примітку вище про це).
kill -9 %вбити. Сигнал 9 не можна ігнорувати, а також сигнал призупинення не може. Послідовність клавіатур CTRL + Z теоретично можна ігнорувати - але це не на практиці.