Co CTRL + 4 (i CTRL + \) robi w bash?


22

Właśnie przypadkiem dowiedziałem się, że CTRL+ 4 zamyka programy odczytujące stdindane wejściowe z wiersza poleceń.

Tak to wygląda, gdy wpisuję CTRL+ 4lub CTRL+ / w czytających programachstdin

$ cat
wefwef
wefwef
^\Quit
$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
^\Quit
$

Zostaje ^\Quitwyświetlony, a następnie program zamyka się. Jaka jest różnica tego w porównaniu do używania ^Club ^D? Co ma ^\Quitzrobić?

Edycja : Odkryłem, że CTRL+ \robi to samo.

Odpowiedzi:


37

Ctrl + 4 wysyła ^ \

Terminale wysyłają znaki (a ściślej bajty), a nie klucze. Po naciśnięciu klawisza reprezentującego znak, który można wydrukować, terminal wysyła ten znak do aplikacji. Większość klawiszy funkcyjnych jest zakodowanych jako sekwencje specjalne: sekwencje znaków rozpoczynające się od znaku 27. Niektóre słowa kluczowe postaci Ctrl+ characteri kilka klawiszy funkcyjnych są wysyłane jako znaki kontrolne - w zestawie znaków ASCII , który wszystkie współczesne komputery używać jako podstawy (Unicode, ISO Latin- n, itd. to nadzbiory ASCII), 33 znaki to znaki sterujące: znaki od 0 do 31 i 127. Znaki sterujące nie są drukowalne, ale mają na celu działanie w aplikacjach; na przykład znak 10, którym jest Control-J (zwykle zapisywany ^ J), jest znakiem nowego wiersza, więc gdy terminal wyświetla ten znak, przesuwa kursor do następnego wiersza, zamiast wyświetlać glif. Sam znak zmiany znaczenia jest znakiem kontrolnym ^ [(wartość 27).

Nie ma wystarczającej liczby znaków kontrolnych, aby zakryć wszystkie Ctrl+ słowa characterkluczowe. Tylko litery i znaki @[\]^_?mają odpowiedni znak kontrolny. Kiedy naciśniesz Ctrl+ 4lub Ctrl+ $(który, jak zakładam, to Ctrl+ Shift+ 4), terminal musi wybrać coś do wysłania. W zależności od terminala i jego konfiguracji istnieje kilka typowych możliwości:

  • Terminal ignoruje Ctrlmodyfikator i wysyła znak 4lub $.
  • Terminal wysyła sekwencję zmiany znaczenia, która koduje dokładnie wciśnięty klawisz i modyfikatory.
  • Terminal wysyła inny znak sterujący.

Wiele terminali wysyła znaki sterujące dla niektórych kluczy w wierszu cyfr:

  • Ctrl+ 2→ ^ @
  • Ctrl+ 3→ ^ [
  • Ctrl+ 4→ ^ \
  • Ctrl+ 5→ ^]
  • Ctrl+ 6→ ^^
  • Ctrl+ 7→ ^ _
  • Ctrl+ 8→ ^?

Nie wiem, gdzie powstała ta konkretna konwencja.

Ctrl+ |wysyła ten sam znak, ponieważ jest Ctrl+ Shift+, \a terminal wysyła ^ \ niezależnie od tego, czy naciśnięto klawisz Shift, czy nie.

^ \ kończy pracę

Sam terminal (a dokładniej ogólna obsługa terminala w jądrze) interpretuje specjalnie kilka znaków kontrolnych. Ta interpretacja może być skonfigurowana do mapowania różnych znaków lub wyłączona przez aplikacje, które same chcą przetwarzać znaki. Jedną z dobrze znanych takich interpretacji jest to, że ^ M, znak wysyłany za pomocą Returnklawisza, wysyła bieżącą linię do aplikacji, jeśli terminal jest w trybie gotowania , w którym aplikacje odbierają wejście linia po linii.

Kilka znaków wysyła sygnały do aplikacji na pierwszym planie. ^ C wysyła sygnał przerwania (SIGINT), który konwencjonalnie nakazuje aplikacji zatrzymać pracę i przeczytać następne polecenie użytkownika. Nieinteraktywne aplikacje zwykle zamykają się. ^ \ wysyła sygnał wyjścia (SIGQUIT), który konwencjonalnie nakazuje aplikacji zakończenie pracy tak szybko, jak to możliwe, bez zapisywania czegokolwiek; wiele aplikacji nie zastępuje domyślnego zachowania, które polega na natychmiastowym zabiciu aplikacji¹. Więc kiedy naciśniesz Ctrl+ 4(lub cokolwiek, co wysyła znak ^ \) w catlub bc, z których żadne nie zastępuje domyślnego zachowania, aplikacja zostanie zabita.

Sam terminal drukuje ^\część wiadomości: jest to wizualne przedstawienie wpisanego znaku, a terminal jest w trybie gotowym i włączonym echo (znaki są wyświetlane przez terminal zaraz po ich wpisaniu, w przeciwieństwie do tryb bez echa, w którym znaki są wysyłane tylko do aplikacji, która może, ale nie musi, wyświetlać je). QuitCzęść pochodzi z bash: to zauważy, że proces jej dziecko zmarło od A wyjść sygnału, a to jest jego sposób powiadomieniem.

Powłoki obsługują wszystkie popularne sygnały, więc jeśli wpiszesz ^ \ w powłoce, nie zabijesz sesji, po prostu pojawi się nowy monit, podobnie jak ^ C.

Możesz grać z ustawieniami terminala za pomocą sttypolecenia.

¹ Tradycyjnie generuje zrzut pamięci , ale obecnie wiele systemów domyślnie go wyłącza.


SIGINT zabija pierwszoplanową grupę procesów, a SIGQUIT zabija ją za pomocą zrzutu pamięci. Oba sygnały mogą być obsługiwane. Nie jestem pewien, co masz na myśli, czytając następne polecenie . Systemy nie wyłączają zrzutów pamięci innych niż poprzez ustawienie początkowego limitu wielkości zrzutu rdzeniowego na 0 (nie trudny, na ogół możesz go podnieść).
Stéphane Chazelas,

@ StéphaneChazelas W programie, który wykonuje interakcje użytkownika, typową semantyką SIGINT jest anulowanie bieżącego polecenia użytkownika i umożliwienie mu interakcji z programem, tj. Powrotu do głównej pętli poleceń. Z drugiej strony nie pamiętam programu, w którym SIGQUIT nie wychodzi (z wyjątkiem błędów w module obsługi sygnału). Rzeczywiście sposobem, w jaki wiele systemów domyślnie wyłącza zrzuty pamięci, jest ustawienie miękkiego limitu wielkości zrzutu pamięci na 0, pozostawiając użytkownikom swobodę zmiany tego ustawienia domyślnego, jeśli chcą.
Gilles 'SO - przestań być zły'

To jest wyjątek. SIGINT zabija aktualnie uruchomione zadanie. Tylko kilka aplikacji rozszerzyłoby to, aby zabić swoje własne zadanie „pierwszego planu”. Musisz myśleć o lesslub vim. Zauważ, że w cmd | less, na CTRL-Cogół zabija cmd(podczas lessgdy jest obsługiwane, aby anulować bieżącą akcję (jak wyszukiwanie)) (ciąg dalszy)
Stéphane Chazelas

Uważam, że brzmienie twojej odpowiedzi jest mylące w tym względzie. Fakt, że SIGQUIT zasadniczo nie jest obsługiwany, polega na tym, że nie jest on używany w ten sam sposób. Naciskasz CTRL-C, aby przerwać to, co obecnie robisz. `CTRL- \ 'używałbyś bardzo okazjonalnie do debugowania w celu wygenerowania zrzutu podstawowego. Zasadniczo nie ma powodu, dla którego aplikacja chciałaby przeszkadzać.
Stéphane Chazelas,

@ StéphaneChazelas Nie tylko mniej i vim, większość aplikacji terminalowych, które odczytują polecenia użytkownika. Na przykład REPL (bash, dash, ksh, zsh, python, irb, fsharpi, Mathematica,…). To nie jest rzadkie. Twój pierwszy komentarz sprzeciwia się malowaniu SIGINT i SIGQUIT jako zbyt odmiennego, a twój ostatni komentarz sprzeciwia się malowaniu SIGINT i SIGQUIT jako zbyt podobnego, co mnie zastanawia, co jeździsz.
Gilles 'SO - przestań być zły'

7

Oprócz odpowiedzi Gilles pozwól mi dodać, że zawsze możesz wpisać znaki niedrukowalne za pomocą Ctrl-v+ key( Ctrl-v+ Ctrl+4w tym przypadku + ) i sprawdzić kod znaku za pomocą

$ printf '^\' | od -An -tu    # input ^\ as C-v C-4
28

otrzymasz kod dziesiętny znaku, który jak możesz się wpisać man asciiodpowiada separatorowi plików (FS) .


Więc co robi ctrl + v? Jestem przyzwyczajony do tego, że „wklejam schowek”.
JDługosz

2
@ JDługosz: Ctrl-V informuje terminal, aby nie interpretował następującego znaku. Niefortunnym faktem jest, że kombinacje klawiszy GUI przejęły te znaki kontrolne, powodując niepotrzebne zamieszanie. Kiedyś Linux używał Alt- [Key] do klawiszy GUI (np. Alt-C / Alt / V do kopiowania / wklejania), ale wtedy ludzie najwyraźniej uważali, że robienie tego samego co Windows jest ważniejsze; tymczasem użytkownicy komputerów Mac nadal nie mają problemu z użyciem klawisza Command zamiast Ctrl do tych operacji.
celtschk

(Krótsze) polecenie to printf '%d\n' '"^\':?
Izaak
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.