Warum tötet Ctrl-C das Terminal nicht selbst?

38

Das Terminal läuft, wenn wir es öffnen.

luvpreet@DHARI-Inspiron-3542:/$

Ich habe es gerade geöffnet. Also, wenn ich Ctrl+ drücke C, warum tötet es sich nicht selbst und schließt das Terminal?

luv.preet
quelle
21
Terminal läuft nicht im Terminal ;-)
Pilot6
3
Fragen,
Janus Troelsen

Antworten:

47

Ctrl+ Cist das Interruptsignal. Wenn Sie dies in ein Terminal eingeben, sendet bash SIGINT an den Job im Vordergrund. Wenn es keinen Job gibt (was der Fall ist, wenn Sie gerade ein Terminal geöffnet haben), passiert nichts. Das Terminal-Emulator-Programm ist kein Job, der in der Shell ausgeführt wird. Daher empfängt es das Signal nicht und wird nicht geschlossen.

Wenn Sie das Terminal mit einem Steuerschlüssel schließen möchten, verwenden Sie Ctrl+ D(EOF), wodurch die Bash beendet wird (und das Terminal ebenfalls geschlossen wird).

Siehe auch: Bash Anfängerleitfaden zu Signalen und mehr Details Funktionsweise der Signalverarbeitung
Hinweis: Diese Antwort wurde bearbeitet, seit Kommentare gepostet wurden

Zanna
quelle
4
Der richtige Begriff ist, dass die Shell das Signal "einfängt". Eine andere Geschichte ist, wenn Sie ein Terminalfenster aus einem anderen Fenster heraus starten. Wenn Sie Strg + C an das übergeordnete Fenster senden, wird der untergeordnete Prozess abgebrochen.
Sergiy Kolodyazhnyy
1
Darüber hinaus können GUI-Fenster angewiesen werden, bestimmte Signale vom X11-Server abzufangen. Auf diese Weise können Sie Popups erhalten, die Sie über nicht gespeicherte Arbeiten informieren, oder Tabs wie in Browsern öffnen
Sergiy Kolodyazhnyy
8
@chrylis Das Terminal-Programm sendet nur das Strg-C-Zeichen, es ist eigentlich die Kernel-Tty-Schicht, die es in das Signal verwandelt.
Random832
3
@chrylis: Und das Terminal oder ein darin ausgeführtes Programm - zum Beispiel ein Texteditor - könnte Ctl-C in eine andere Aktion übersetzen.
Jamesqf
3
Ich glaube nicht, bashdass Programme beendet werden, wenn Strg-C gedrückt wird. Es teilt dem Kernel lediglich mit, welche Prozessgruppe aktiv ist, und der Kernel generiert ein Signal für diese Prozessgruppe, wenn er Strg-C vom Terminalprogramm empfängt.
Kasperd
32

Der ^CTastenanschlag ist, wie andere Tastenanschläge *, keine Zauberei - er sendet einen Schlüsselcode an das Programm, auf das der Fokus liegt. (In X ist der Schlüsselcode 54 für die Cmit einem Modifikator von 0x4 für Ctrl.) Das Programm, das den Schlüsselstrom empfängt, ist dafür verantwortlich, dass die entsprechenden Aktionen ausgeführt werden . Beachten Sie, dass in vielen GUI-Anwendungen der Tastendruck in die Zwischenablage kopiert wird.

Wenn ein GUI-Terminal-Emulator (z. B. Konsole) oder ein virtuelles Terminal einen von ihm interpretierten Tastenanschlag empfängt ^C, kann er eine der folgenden drei Aktionen ausführen . Befindet sich das Terminal im Raw-Modus , hat das laufende Programm das Terminal aufgefordert, keine Sondertasten selbst zu bearbeiten und diese direkt an das Programm weiterzuleiten. Einige Programme, die erweiterte Funktionen wie die Zeilenbearbeitung unterstützen, empfangen in einigen Konfigurationen Tastatureingaben zwischen vollständigen rohen Tastenanschlägen und verarbeiteten Textzeilen. bashBeispielsweise werden Tastenanschläge einzeln empfangen. ^Cwird vom Terminal interpretiert, aber die Rücktaste wird unverändert an die Shell gesendet.

Die meisten Programme verwenden jedoch den gekochten Modus (da dieser nicht roh ist), in dem das Terminal einige grundlegende Tastenanschläge interpretiert, bevor sie tatsächlich an das Programm gesendet werden (daher können Sie die Rücktaste in verwenden cat). In diesem Modus übersetzt das Terminal selbst den ^CTastenanschlag in ein SIGINTSignal und sendet es an den untergeordneten Prozess. Da das Terminal das Signal erzeugt hat, wird es nicht verwirrt und terminiert.

  • SysRq Ist wirklich Magie.
chrylis -on strike-
quelle
Offensichtlich hier nicht überrelevant, aber für das allgemeine Rechnen gibt es da draußen mehr magische Tastenanschläge. Am bekanntesten ist , Ctrl+ Alt+ Deletein der Windows - Welt, wo die Tastenkombination ziemlich nah an Magie ist (es kann verwendet werden , um Windows zur Arbeit zu kommen, das ist ziemlich magisch an und für sich!), Da es zu Interrupt in das System hartcodiert ist und so ziemlich alles außer Kraft setzen - SysRqin diesem Sinne ziemlich ähnlich .
KRyan
7
Bash verwendet nicht den Raw-Modus , sondern den Modus " Zeichen für Zeichen", dh " cbreak/" -icanon. Er verlässt jedoch den isigModus und empfängt echte Signale, wenn Sie Tasten drücken, die diesen zugeordnet sind. Es SIGINTwird so gehandhabt, wie Sie es beschrieben haben (es bricht nicht nur die Zeilenbearbeitung ab, es bricht auch alle internen Befehle ab, die möglicherweise in einer Schleife ausgeführt werden) und ignoriert SIGTSTPund vollständig SIGQUIT. Andere Programme, wie z. B. vi, möglicherweise nicht.
Random832
1
@KRyan Ctrl+ Alt+ Deleteverwendet noch mehr Magie zu sein , als es heute ist - blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083 . Obwohl ich im Grunde genommen ein Linux-Mensch bin, bin ich oft sehr beeindruckt davon, inwieweit Windows in den Anfängen mit so begrenzten Ressourcen die Dinge benutzerfreundlich und logisch gemacht hat.
Muzer
Auf einigen Betriebssystemen werden die Tastendrücke tatsächlich vor dem Terminalemulator abgerufen, selbst wenn ein anderes Programm den Fokus auf das System hat (Window Manager, denke ich?). Wenn Sie Tastenkombinationen zum Öffnen von Fenstern, Öffnen von Anwendungen und Auslösen von Skripten konfigurieren können, werden die gedrückten Tasten vor dem Senden an den Terminalemulator auf von Ihnen konfigurierte Tastenkombinationen überprüft. Und ein anderes Beispiel, wenn Sie keine Anwendungen geöffnet haben, ^cwird den Fenstermanager nicht beenden :). Kann nicht auf rohen / gekochten Charakter auf einmal Zeug kommentieren, aber die Antwort ist genau richtig darüber, wie dieser Tastenanschlag generiertSIGINT
Ajay
2
" Gekochter Modus (weil er nicht roh ist)": Ich bin ... sprachlos. Nach all den Jahren habe ich nie die Verbindung hergestellt.
Isanae
8

^Cwird normalerweise stty -adem SIGINTSignal zugeordnet (siehe man 7 signal).

Ein nicht abgefangener SIGINTunterbricht den laufenden Prozess, ABER ...

SIGINT ist eines der Signale, für die ein Prozess das Verhalten festlegen kann ("Abfangen eines Signals").

Was Sie "das Terminal" nennen, fängt SIGINTan und geht wieder an die Arbeit.

Waltinator
quelle
7

Als Anfänger fehlte mir der Teil, dass ich bei der Verwendung der Befehlszeile tatsächlich zwei separate Programme verwendete, ein Terminal und eine Shell (z. B. bash).

Die Shell ist das, was Sie wahrscheinlich bereits kennen, ein Programm, das als Eingabebefehle oder Skripte sie ausführt und ihre Ausgabe druckt.

Das Terminal auf der anderen Seite ist wie ein Mann in der Mitte zwischen dem Benutzer und einem Programm (bei dem es sich normalerweise um eine Shell wie Bash oder Fish handelt). Das Terminal liest die Eingabe beispielsweise von der Tastatur, verarbeitet sie möglicherweise auf irgendeine Weise und leitet sie an das andere Programm weiter (bash).

Dies funktioniert auch in umgekehrter Richtung: Wenn das andere Programm etwas ausgibt, das auf das Terminal umgeleitet wird, ist es die Aufgabe des Terminals, das auf dem Bildschirm auszugeben. Zwischen der Eingabe und dem Ausdruck auf dem Bildschirm kann das Terminal die eingegebenen Daten auf verschiedene Arten interpretieren.

Zum Beispiel, wenn ein Programm die folgende Sequenz ausgibt:

\e[0;31m some extra foobar text

Das Terminal gibt auf dem Bildschirm "zusätzlichen Text" mit roten Buchstaben aus. Dies liegt daran, dass das Terminal diesen seltsamen Code auf eine spezielle Art und Weise behandelt. Dieser Code weist es an, die folgende Ausgabe in Rot zu drucken.

Wenn der Benutzer drückt Ctrl - C, ist das einzige Besondere daran, dass das Terminal es auf besondere Weise behandelt. An dieser Tastenfolge ist nichts Besonderes. Insbesondere weist dies darauf hin, dass das Interrupt-Signal (SIGINT) an den Prozess gesendet wird, der im Terminal ausgeführt wird, dh an die Shell. Wenn zu diesem Zeitpunkt ein Programm existiert, das von der Shell erzeugt wurde und gerade im Vordergrund läuft, empfängt es auch das Signal. Jetzt hat die Shell einen speziellen Handler für dieses Signal und es passiert nichts. Die meisten Programme haben jedoch die Standard-Handler, die in SIGINTs Fall einfach beendet werden.

user183833
quelle
5

Jedem Signal ist eine Standardaktion zugeordnet. Die Standardaktion für ein Signal ist die Aktion, die ein Skript oder Programm ausführt, wenn es ein Signal empfängt.

Ctrl+ Csendet das "Interrupt" -Signal ( SIGINT ), das standardmäßig den Prozess an den im Vordergrund laufenden Job beendet.

Ctrl+ Dteilt dem Terminal mit, dass es eine EOF für die Standardeingabe registrieren soll , die als Verlangen nach dem Verlassen interpretiert wird .

Ein Prozess kann das INT-Signal ignorieren, und Bash tut dies, wenn es im interaktiven Modus ausgeführt wird.

Aus dem Handbuch :

Wenn bash interaktiv ist und keine Traps vorhanden sind, ignoriert es SIGTERM (damit kill 0 keine interaktive Shell beendet) und SIGINT wird abgefangen und behandelt (damit das eingebaute Warten unterbrochen werden kann). In allen Fällen ignoriert bash SIGQUIT. Wenn die Jobsteuerung aktiviert ist, ignoriert bash SIGTTIN, SIGTTOU und SIGTSTP.


Verstehen Sie es mit Falle :

trap ist eine in die Shell integrierte Funktion, die auf Hardware-Signale und andere Ereignisse reagiert. Es definiert und aktiviert Handler, die ausgeführt werden, wenn die Shell Signale oder andere spezielle Bedingungen empfängt.

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

-l Drucken Sie eine Liste der Signalnamen und der entsprechenden Nummern.
-pZeigen Sie die Trap-Befehle an, die jedem SIGNAL_SPEC zugeordnet sind.

arg soll gelesen und ausgeführt werden, wenn die Shell das Signal sigspec empfängt. Jede Sigspec ist entweder ein Signalname oder eine Signalnummer. Bei Signalnamen wird die Groß- und Kleinschreibung nicht berücksichtigt, und das SIG-Präfix ist optional.

Wenn ein sigspec ist 0 oder EXIT , ist arg , wenn die Shell beendet ausgeführt. Um dies zu verstehen, schließen Sie das Terminal und öffnen Sie es, nachdem Sie die folgende Zeile in der .bashrcDatei bearbeitet haben .

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

Strg + D ähnelt dem exitBefehl zum Verlassen des Terminals.

Wenn Sie möchten, dass Bash auch im interaktiven Modus beim Empfang des INT-Signals beendet wird, können Sie Folgendes hinzufügen ~/.bashrc:

trap 'exit' INT

oder

trap 'exit' 2
Gänseblümchen
quelle
1
es scheint echt !!
luv.preet