Завершение процесса в Unix вместо его прерывания

12

В Unixкомандной строке, если я нажимаю Ctrl-C, это не завершает процесс, а скорее прерывает его, и я возвращаюсь к приглашению оболочки.

Итак, у меня есть следующие два вопроса:

    1. Есть ли способ увидеть список всех прерванных процессов и завершить их?
    1. Какую комбинацию клавиш нажать, чтобы завершить процесс, а не прерывать его?
Николас Аларкон Рапела
источник

Ответы:

20

Ctrl+ Cотправляет SIGINT. По умолчанию это завершает приложение.

Вы путаете это с тем Ctrl-Z, что приложение в bash приостанавливается.

Игнасио Васкес-Абрамс
источник
7

Исторически было три сигнала, связанных с нажатиями клавиш, это были

  • SIGINT (Прерывание) обычно Ctrl+ CилиDel
  • SIGQUIT - Выход - Обычно связан с Ctrl+\
  • SIGSUSP Suspend - обычно связан с Ctrl+Z

На некоторых разновидностях * nix есть и другие связанные сигналы, вы можете проверить привязки клавиатуры, используя команду

stty -a

В моей системе OS / X это выдает следующий вывод

speed 9600 baud; 65 rows; 213 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
    -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
    -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
    -ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
    -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
    eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
    min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
    stop = ^S; susp = ^Z; time = 0; werase = ^W;

Обратите внимание, что в этом случае kill не является сигналом KILL, это связано с очисткой текущего входного буфера.

Вы можете добиться большего успеха с остановкой процессов с использованием SIGQUIT, но это может быть не так, поскольку процесс может перехватить сигнал и проигнорировать его.

Не существует понятия списка «прерванных» процессов, поскольку процесс либо перехватил и проигнорировал прерывание, либо завершился. Вы можете получить список приостановленных процессов, набрав задание

Стив Уит
источник
Интересно, что я показываю ^ Q и ^ S (как и вы), но настроил stty -ixonтак, чтобы они были пропущены. Я думаю, что они изменятся на <undef>.
Приостановлено до дальнейшего уведомления.
Я не нахожу SIGSUSP на страницах man ни моего OS X-бокса, ни моего Debian Lenny-бокса. Вроде бы SIGTSTP.
dmckee --- котенок экс-модератора
DEL - ах, план 9 ...
new123456
5

Множество правильных ответов, но ни одного полного.

  1. Как говорили многие другие: Control-C обычно посылает сигнал Unix SIGINT, и поведение по умолчанию (из программ, которые его не переопределяют) - «завершить процесс». Программа может игнорировать этот сигнал или предпринимать иные действия, если того пожелает.
  2. Вы также можете отправить SIGQUIT с клавиатуры с помощью Control- \. Разница здесь в том, что по умолчанию процесс запишет файл ядра, а затем выйдет. Программа может игнорировать этот сигнал или предпринимать иные действия, если того пожелает.
  3. Чтобы завершить работу с предубеждением и не допуская остановки процесса, используйте SIGKILL, который по умолчанию не привязан ни к одному ключу. Вместо этого вы обычно отправляете его, используя kill (1)команду и указывая сигнал для отправки, как в

    $ kill -9 <process ID>
    

    или мнемонически

    $ kill -KILL <process ID>
    

    Этот сигнал обрабатывается непосредственно ОС, и программа не может переопределить поведение по умолчанию.

  4. Если ваша оболочка поддерживает управление заданиями, она также может поддерживать встроенную версию, killкоторая поддерживает идентификацию заданий с помощью %символа, как в ответе подиума .

  5. Чтобы приостановить процесс возобновляемым способом, вы используете Control-z, который отправляет SIGTSTP. Вы возобновляете такой процесс, либо fgпродолжая управлять терминалом, либо bgзапускать его без сохранения контроля над терминалом (но по умолчанию все равно отправляете свой вывод туда).
dmckee --- котенок экс-модератора
источник
Кроме того, дамп ядра на SIGQUIT зависит от многих административных деталей. ulimit -c, coreadm (1M) в Solaris и т. д. Еще одно замечание - fg отправляет сигнал SIGCONT, который заставляет процесс возобновить свою работу.
Тадеуш А. Кадлубовски
1
  1. чтобы увидеть список фоновых процессов: jobs

    убить: kill %1(подставьте 1 с соответствующим идентификатором задания, как в jobsвыводе)

  2. смотрите здесь
Сообщество
источник
1

Ctrl-C отправляет SIGINT, что по умолчанию приводит к завершению процесса, но может быть захвачено ( \bin shиспользуя trap).

SIGKILL - это необратимый сигнал убийства.

В третий раз я думаю, что это правильно: я проверил все по документам. Посмотрим.

Чарльз Стюарт
источник
SIGKILL не может быть пойман
Ага. Я уже исправил это ...
Чарльз Стюарт
1

Это не понятно большинству новичков в терминале, но если ваша проблема в том, что вы находитесь в интерактивной программе, и вы не можете понять, как выбраться из нее, довольно часто qэто происходит. Например, это ключ для выхода less, который man, помимо прочего , является программой, которую вы получаете при просмотре страниц.

Некоторые программы имеют другие сочетания клавиш для выхода. В vimили vi, используйте ESC:wq. В emacs, использовать Control-C Control-X. В nanoили pico, используйте Control-X. Обратите внимание, что в этих примерах есть тонкости, в частности, касающиеся того, сохраняют ли эти ярлыки какие-либо изменения, которые вы, возможно, внесли в файл, который вы редактируете.

asmeurer
источник
Так какой же стандарт?
Pacerier
0

Многие процессы могут установить обработчик прерывания для перехвата сигнала прерывания, но те, которые не прерывают его по умолчанию.

Чтобы принудительно завершить процесс, вы можете отправить SIGQUIT (Ctrl- \).

NJD
источник
SIGQUIT может быть пойман в ловушку, SIGKILL не может быть.
Чарльз Стюарт
1
@Charles: еще одно отличие состоит в том, что SIGQUIT по умолчанию сбрасывает ядро, а SIGKILL - нет.
Тадеуш А. Кадлубовски
0

Кажется, что другие ответы - вероятный сценарий, но также возможно, что вы выполняете сценарий, который неправильно обрабатывает его дочерние элементы. Недавно я столкнулся с похожим сценарием, где уничтожение сценария не приведет к уничтожению дочерних процессов этого сценария.

В общем, если вы попадаете в эту ситуацию, вам придется пересмотреть все процессы, которые вы запускаете. Вы должны просмотреть справочную страницу для PS. ( man ps) Мне особенно нравится использование ps auxwf, которое показывает отношения родитель / потомок между процессами. pstreeделает что-то подобное. Вы должны запустить это из другого терминала перед тем, как убить процесс, чтобы увидеть, как все выглядит в обычной ситуации, и определить дочерние процессы.

Если вы затем убьете (с помощью ^ C) этот основной процесс, снова проверьте вывод команды ps, чтобы увидеть, изменилось ли что-нибудь. Если дочерние процессы все еще существуют, вы можете убить их с помощью killкоманды. (см. man kill)

ДЕРЕВО
источник