Dlaczego Ctrl-C nie zabija samego terminala?

39

Terminal działa, gdy go otwieramy.

luvpreet@DHARI-Inspiron-3542:/$

Właśnie to otworzyłem. Kiedy naciskam Ctrl+ C, dlaczego nie zabija się i nie zamyka terminala?

luv.preet
źródło
21
terminal nie działa w terminalu ;-)
Pilot6
3
na temat tego, dlaczego działa control-d: unix.stackexchange.com/a/110248/14305
Janus Troelsen

Odpowiedzi:

48

Ctrl+ Cto sygnał przerwania. Kiedy wpiszesz to w terminalu, bash wysyła SIGINT do zadania na pierwszym planie. Jeśli nie ma pracy (co dzieje się po otwarciu terminala), nic się nie dzieje. Program emulatora terminali nie działa w powłoce, więc nie odbiera sygnału i nie zamyka się.

Jeśli chcesz zamknąć terminal za pomocą klawisza sterującego, użyj Ctrl+ D(EOF), co powoduje wyjście bash'a (i również zamyka terminal).

Zobacz także: Przewodnik Bash dla początkujących na temat sygnałów i bardziej szczegółowo Jak działa obsługa sygnałów
Uwaga: Ta odpowiedź została edytowana od czasu opublikowania komentarzy

Zanna
źródło
4
Właściwym terminem jest to, że powłoka „złapie” sygnał. Inna historia polega na uruchomieniu okna terminala z innego okna. Wysłanie ctrl + c do okna nadrzędnego zabije proces potomny.
Sergiy Kolodyazhnyy
1
Ponadto okna GUI można również poinstruować, aby przechwytywały określone sygnały pochodzące z serwera X11. W ten sposób możesz wyświetlać wyskakujące okienka z powiadomieniem o niezapisanej pracy lub otwierać karty jak w przeglądarkach
Sergiy Kolodyazhnyy
8
@chrylis program terminalowy wysyła po prostu znak ctrl-c, w rzeczywistości jest to warstwa tty jądra, która zamienia go w sygnał.
Random832
3
@chrylis: A terminal lub działający w nim program - na przykład edytor tekstowy - mogą tłumaczyć Ctl-C na inną akcję.
jamesqf
3
Nie sądzę, bashże zakończy działanie jakiegokolwiek programu po naciśnięciu ctrl-c. Po prostu poinformuje jądro, która grupa procesów jest aktywna, a jądro wygeneruje sygnał do tej grupy procesów, gdy otrzyma ctrl-c z programu terminalowego.
kasperd
32

Klawisz ^C, podobnie jak inne klawisze *, nie jest magiczny - wysyła kod do dowolnego programu. (W X kod klucza to 54 dla Cmodyfikatora 0x4 dla Ctrl.) Program, który odbiera strumień kluczy, jest odpowiedzialny za zrobienie z nimi czegoś odpowiedniego - pamiętaj, że w wielu aplikacjach GUI naciśnięcie klawisza jest kopiowane do schowka.

Gdy emulator terminala GUI (np. Konsole) lub terminal wirtualny otrzyma naciśnięcie klawisza, które interpretuje ^C, może wykonać jedną z trzech czynności. Jeśli terminal jest w trybie surowym , wówczas uruchomiony program poprosił go, aby nie wykonywał żadnej obsługi samych kluczy specjalnych i przekazał je bezpośrednio do programu. Niektóre programy obsługujące zaawansowane funkcje, takie jak edycja linii, są wprowadzane za pomocą klawiatury w pewnej konfiguracji pomiędzy pełnymi surowymi naciśnięciami klawiszy a przetworzonymi wierszami tekstu; bash, na przykład, odbiera naciśnięcia klawiszy pojedynczo. ^Cjest interpretowany przez terminal, ale klawisz Backspace jest wysyłany do powłoki w niezmienionej postaci.

Większość programów korzysta jednak z trybu gotowego (ponieważ nie jest on surowy), w którym terminal interpretuje niektóre podstawowe naciśnięcia klawiszy przed faktycznym wysłaniem ich do programu (dlatego można użyć backspace w cat). W tym trybie sam terminal przekształca ^Cnaciśnięcie klawisza na SIGINTsygnał i wysyła go do procesu potomnego. Ponieważ terminal wygenerował sygnał, nie pomyli się i nie zakończy połączenia.

  • SysRq naprawdę jest magią.
Chrylis-on strike-
źródło
Oczywiście nie ma tu większego znaczenia, ale w przypadku komputerów ogólnych jest więcej magicznych naciśnięć klawiszy. Najbardziej znane: Ctrl+ Alt+ Deletew świecie Windows, w którym kombinacja klawiszy jest dość zbliżona do magii (można go użyć do uruchomienia systemu Windows, to samo w sobie jest dość magiczne!), Ponieważ jest zakodowane w systemie, aby przerwać i zastępują prawie wszystko - całkiem podobne SysRqw tym sensie.
KRyan,
7
Bash nie używa trybu raw - używa trybu znak po czasie tj. cbreak/ -icanon, Ale pozostawia isigustawiony tryb i odbiera rzeczywiste sygnały po naciśnięciu mapowanych do nich klawiszy. Obsługuje to SIGINT, zachowując się tak, jak opisano (nie tylko anuluje edycję linii, ale także anuluje wszelkie wewnętrzne polecenia, które mogą być uruchomione w pętli) i całkowicie ignoruje SIGTSTPi SIGQUIT. Inne programy, takie jak vi, mogą nie.
Random832,
1
@KRyan Ctrl+ Alt+ Deletebył jeszcze bardziej magiczny niż obecnie - blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 . Chociaż w głębi serca jestem osobą związaną z Linuksem, często jestem pod dużym wrażeniem stopnia, w jakim system Windows sprawił, że na początku jego działania były przyjazne dla użytkownika i logiczne przy tak ograniczonych zasobach.
Muzer
W niektórych systemach operacyjnych, nawet jeśli inny program skupia się na systemie (chyba menedżer okien?) Faktycznie uzyskuje naciśnięcia klawiszy, zanim zrobi to emulator terminala. Jeśli jesteś w stanie skonfigurować skróty klawiaturowe w celu przyciągania okien, otwierania aplikacji, uruchamiania skryptów, to zanim naciśnięte klawisze zostaną wysłane do emulatora terminali, sprawdzane są wszystkie skonfigurowane skróty. A inny przykład, jeśli nie masz otwartych aplikacji ^c, nie zabije menedżera okien :). Nie jestem w stanie wypowiedzieć się na temat postaci surowej / gotowanej na raz, ale odpowiedź jest na temat tego, jak generuje to naciśnięcie klawiszaSIGINT
Ajay
2
tryb gotowany (ponieważ nie jest surowy)”: Jestem ... oniemiały. Po tylu latach nigdy nie nawiązałem połączenia.
isanae
8

^Cjest zwykle mapowany (patrz stty -a) na SIGINTsygnał (patrz man 7 signal).

Nieprzechwycony SIGINTprzerywa trwający proces, ALE ...

SIGINT jest jednym z sygnałów, dla których proces może określić zachowanie („Złapanie sygnału”).

To, co nazywacie „terminalem”, łapie SIGINTi wraca do pracy.

waltinator
źródło
7

Kiedy byłem początkujący, brakowało mi części, że kiedy korzystałem z wiersza poleceń, faktycznie używałem dwóch oddzielnych programów, terminala i powłoki (np. Bash)

Powłoka jest tym, co już pewnie wiesz, programem, który przyjmuje polecenia wejściowe lub skrypty, wykonuje je i wypisuje swoje dane wyjściowe.

Terminal po drugiej stronie jest jak człowiek pośrodku między użytkownikiem a programem (który to program jest zwykle powłoką jak bash lub fish). Terminal odczytuje dane wejściowe na przykład z klawiatury, być może przetworzy je w jakiś sposób i przekieruje do innego programu (bash).

Działa to również w drugą stronę, gdy inny program wypisuje coś, że coś jest przekierowywane do terminala, wówczas zadaniem terminalu jest wyprowadzenie tego czegoś na ekran. Pomiędzy pobraniem danych wejściowych a wydrukowaniem ich na ekranie terminal może interpretować dane wejściowe na różne sposoby.

Na przykład, jeśli program wyświetla następującą sekwencję:

\e[0;31m some extra foobar text

Terminal wyświetli na ekranie „dodatkowy tekst foobar” z czerwonymi literami. Wynika to z faktu, że terminal wybiera specjalny sposób traktowania tego dziwnego kodu, który podpowiada mu, aby wydrukował następujący wynik na czerwono.

Podobnie, gdy użytkownik naciska Ctrl - C, jedyną specjalną rzeczą w tym jest to, że terminal decyduje się traktować go w specjalny sposób, nie ma nic specjalnego w tej sekwencji klawiszy. W szczególności sugeruje to wysłanie sygnału przerwania (SIGINT) do procesu działającego wewnątrz terminala, czyli powłoki. Jeśli w tym momencie istnieje jakikolwiek program, który został odrodzony przez powłokę i aktualnie działa na pierwszym planie, również odbiera sygnał. Teraz powłoka ma specjalny moduł obsługi tego sygnału i nic się nie dzieje. Ale większość programów ma domyślne programy obsługi, które w przypadku SIGINT po prostu wychodzą.

użytkownik183833
źródło
5

Każdy sygnał ma przypisaną domyślną akcję. Domyślną akcją dla sygnału jest akcja wykonywana przez skrypt lub program po otrzymaniu sygnału.

Ctrl+ Cwysyła sygnał „przerwania” ( SIGINT ), który domyślnie kończy działanie na zadaniu uruchomionym na pierwszym planie.

Ctrl+ Dmówi terminalowi, że powinien zarejestrować EOF na standardowym wejściu, co bash interpretuje jako chęć wyjścia .

Proces może zignorować sygnał INT, a Bash robi to, gdy działa w trybie interaktywnym.

Z instrukcji :

Gdy bash jest interaktywny, przy braku pułapek, ignoruje SIGTERM (tak, że kill 0 nie zabija interaktywnej powłoki), a SIGINT jest przechwytywany i obsługiwany (tak, że wbudowane oczekiwanie jest przerywane). We wszystkich przypadkach bash ignoruje SIGQUIT. Jeśli kontrola zadań jest aktywna, bash ignoruje SIGTTIN, SIGTTOU i SIGTSTP.


Zrozum to za pomocą pułapki :

trap to funkcja wbudowana w powłokę, która reaguje na sygnały sprzętowe i inne zdarzenia. Definiuje i aktywuje procedury obsługi, które mają być uruchamiane, gdy powłoka odbiera sygnały lub inne specjalne warunki.

trap [-lp] [arg] [sigspec …]

-l wydrukuj listę nazw sygnałów i odpowiadających im numerów.
-pwyświetlać polecenia pułapki związane z każdym SIGNAL_SPEC.

arg należy odczytać i wykonać, gdy powłoka odbierze sygnał sigspec. Każdy sigspec jest nazwą sygnału lub numerem sygnału. Nazwy sygnałów nie uwzględniają wielkości liter, a prefiks SIG jest opcjonalny.

Jeśli sigspec ma wartość 0 lub EXIT , arg jest wykonywane po wyjściu powłoki. Aby to zrozumieć, zamknij terminal i otwórz go po edycji kolejnej linii w .bashrcpliku.

trap 'notify-send "Ctrl D pressed"' 0

Ctrl D jest podobny do exitpolecenia, aby wyjść z terminala.

Jeśli chcesz, aby Bash zakończył działanie po otrzymaniu sygnału INT, nawet w trybie interaktywnym, możesz dodać następujące elementy do ~/.bashrc:

trap 'exit' INT

lub

trap 'exit' 2
stokrotka
źródło
1
wydaje się to uzasadnione !!
luv.preet