Kann eine interaktive Shell nicht interaktiv werden oder umgekehrt?
Hinweis: Ich habe mich intensiv mit der grundlegenden Frage befasst: "Was ist der Unterschied zwischen interaktiv und nicht interaktiv?", Und die Ergebnisse meiner Forschung haben mich dazu veranlasst, diese Frage zu stellen .
Diese Frage hat teilweise eine lange Präambel, da es entscheidend ist, welche Art von Definition wir für "interaktiv" verwenden, um sie zu beantworten. Eine Definition kann eine beliebige Bezeichnung für eine bestimmte Menge sein. es könnte verschiedene Eigenschaften beschreiben; oder es kann Ihnen Informationen geben, mit denen Sie das Verhalten vorhersagen und den Zweck verstehen können . Dieser letzte Typ kann als "Aktionsdefinition" oder "dynamische Definition" bezeichnet werden und ist am nützlichsten.
In man 1p sh
wird die folgende Definition einer interaktiven Shell angegeben:
If the -i option is present, or if there are no operands and the shell’s standard input and standard error are attached to a terminal, the shell is considered to be interactive.
Ausgehend von der Erwähnung von "-i Option" und der Verwendung des Wortes "Operanden" bezieht sich dies auf den Aufruf einer Shell , nicht auf Attribute, die in einer laufenden Shell untersucht werden könnten.
Die Bash-Manpage formuliert es etwas anders:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
Die Definition im ersten Satz bezieht sich wiederum nur auf den Beginn einer Shell.
Der zweite Satz (in meiner Lektüre) definiert Bedingungen, die als Proxys verwendet werden, um festzustellen, ob die Shell auf bestimmte Arten gestartet wurde, die als "interaktiv" definiert sind.
Beachten Sie, dass ich diesen Satz nicht so interpretiere: "Eine Bash-Shell ist nur dann interaktiv, wenn sie $-
'i' enthält." $-
scheint nur ein praktischer Indikator zu sein, keine Definition von interaktiv. Dies ist für meine Frage von entscheidender Bedeutung.
Beide (die POSIX- sh
Definition und die Bash-Definition) sind mechanische Definitionen, die angeben, unter welchen Umständen die Bezeichnung "interaktiv" für eine von Ihnen gestartete Shell gilt. Sie sind keine Aktionsdefinitionen, da sie keine Auswirkungen auf dieses Label haben.
Ich sehe jedoch, dass im Rest der Bash-Manpage Verweise auf die Shell verstreut sind, die sich auf bestimmte Weise verhalten, "es sei denn, es handelt sich um eine interaktive Shell" oder "nur in interaktiven Shells oder wenn die Option _____ gesetzt ist". (Es gibt zahlreiche Beispiele und das ist nicht der Hauptpunkt dieser Frage.)
Daher akzeptiere ich, dass "interaktiv" nur eine praktische Bezeichnung für die Sammlung von "interaktiven" Standardverhalten (Optionseinstellungen) ist, die im Rest der Manpage beschrieben werden. Es ist kein grundlegender Begriff oder Gegenstand an sich; Es gibt keine autorisierende Definition außerhalb des Quellcodes der Shell. (Im Gegensatz zu den Begriffen "offener Dateideskriptor" oder "angehaltener Prozess", die sich auf Abstraktionen beziehen, die in das Design des Kernels selbst integriert sind.)
(Während dies auch in der POSIX-Definition von definiert ist sh
, werden in dieser Manpage [ man 1p sh
] weitaus weniger "sofern die Shell nicht interaktiv ist" und ähnliche Anweisungen verwendet als in der POSIX-Definition von man bash
und es werden fast ausschließlich Unterschiede bei der Aufrufzeit behandelt. Ich werde mich daher auf Bash konzentrieren von diesem Punkt an.)
Einige der Auswirkungen einer "interaktiven" Shell sind ohnehin nur zum Zeitpunkt des Aufrufs relevant , z. B. welche Dateien von der Shell bezogen werden, bevor andere Befehle gelesen werden. Es gibt jedoch Implikationen (zumindest in Bash), die jederzeit relevant sind. Daher muss es für jede laufende Shell eine Möglichkeit geben , festzustellen, ob sie interaktiv ist oder nicht.
Das Ausführen set +i
in einer interaktiven Bash-Shell führt dazu, dass 'i' aus dem Inhalt von entfernt wird $-
.
Die Frage ist: Bedeutet dies tatsächlich, dass die Shell nicht mehr interaktiv ist?
Nach der genauen Definition von Bash sollte dies nicht der Fall sein, da nirgendwo in der Definition das Vorhandensein von 'i' erforderlich ist in $-
:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.
Ein striktes Lesen der genauen Definition wirft auch die Frage auf: Wenn die stdin oder stderr eines interaktiven Terminals umgeleitet werden, so dass sie nicht mehr mit Terminals verbunden sind, wird die Shell dann nicht interaktiv?
(Es scheint, dass die Antwort auf diese Frage "Nein" lautet und die Manpage den Modifikator enthalten könnte: "dessen Standardeingabe und Fehler beide mit Terminals verbunden sind ... zum Zeitpunkt des Aufrufs ", aber ich weiß es nicht endgültig.)
Wenn die Antwort "Nein, eine Shell kann nicht nicht interaktiv werden und umgekehrt" lautet , wie lässt sich dann endgültig feststellen, ob die Shell interaktiv ist?
Um es noch anders auszudrücken: Wenn es Verhaltensweisen einer "interaktiven Shell" gibt, die danach fortbestehen set +i
, was wird verwendet , um zu bestimmen, dass diese Verhaltensweisen weiterhin gelten sollen?
Damit niemand daran zweifelt: Es gibt Verhaltensweisen einer interaktiv aufgerufenen Shell, die nach set +i
wie vor bestehen, und Verhaltensweisen einer nicht interaktiv aufgerufenen Shell, die nach wie vor bestehen set -i
. Betrachten Sie als Beispiel den folgenden Auszug aus man bash
:
COMMENTS In a non-interactive shell, or an interactive shell in which the inter- active_comments option to the shopt builtin is enabled (see SHELL BUILTIN COMMANDS below), a word beginning with # causes that word and all remaining characters on that line to be ignored. An interactive shell without the interactive_comments option enabled does not allow comments. The interactive_comments option is on by default in interac- tive shells.
Durch Deaktivieren der interactive_comments
Option können wir also einen Unterschied zwischen interaktiven und nicht interaktiven Shells erkennen. Das Fortbestehen dieses Unterschieds wird durch das folgende Skript veranschaulicht:
#!/bin/bash
# When the testfile is run interactively,
# all three comments will produce an error
# (even the third where 'i' is not in '$-').
# When run noninteractively, NO comment will
# produce an error, though the second comment
# is run while 'i' IS in '$-'.
cat >testfile <<'EOF'
shopt interactive_comments
shopt -u interactive_comments
shopt interactive_comments
echo $-
#first test comment
set -i
echo $-
#second test comment
set +i
echo $-
#third test comment
EOF
echo 'running bash -i <testfile'
bash -i <testfile
echo 'running bash <testfile'
bash <testfile
Dies bestätigt, dass "interaktiv" und " i
im Wert von $-
" nicht gleichwertig sind.
Ein ähnlicher Test ${parameter:?word}
mit einem nicht gesetzten Parameter führt zu ähnlichen Ergebnissen, was wiederum bestätigt, dass dies $-
nicht die "Quelle der Wahrheit" für die Shell-Interaktivität ist.
So, endlich, wo ist die definitive ‚Interaktivität‘ Merkmal einer Schale gespeichert?
Und kann eine interaktive Shell nicht interaktiv werden oder umgekehrt? (... durch Ändern dieses Merkmals?)
quelle
Antworten:
Die Frage, die ich stellen würde, wäre, warum jemand das tun möchte.
Sie können einige Aspekte interaktiver Shells deaktivieren, z.
PS1= PS2=
um die Eingabeaufforderungen zu deaktivierenset +m
um die Jobsteuerung zu deaktivierenzle
und alle Completion-Module in entladenzsh
.Wenn Sie jedoch möchten, dass die Shell nicht mehr interaktiv ist, können Sie stattdessen Folgendes tun:
Zu sagen, dass es den Rest der Befehle erhalten soll
/some/file
(ersetzen durch,/dev/tty
wenn die Befehle weiterhin vom tty-Gerät gelesen werden sollen), obwohl es dennoch einige Unterschiede zu nicht interaktiven Shells geben würde, wie zum Beispiel für das Verhalten vonreturn
oder die Tatsache dass es immer noch Jobkontrolle machen würde oder:So ersetzen Sie Ihre aktuelle interaktive Shell durch eine nicht interaktive Shell, die weiterhin Befehle vom tty-Gerät liest.
Beachten Sie, dass mit bash 4.4 in den meisten anderen Shells
set +i
einbash: set: +i: invalid option
ähnliches Ergebnis erzielt wird .quelle
exec < <(sleep infinity)
in einer interaktiven Shell arbeiten, haben Sie eine interaktive Shell, die nicht sehr interaktiv ist. Die Shell würde sich immer noch als interaktiv betrachten, das$-
würde immer noch enthalteni
, aber Sie könnten nicht. Ich bin mir nicht sicher, ob es noch viel mehr zu besprechen gibt.interactive
, bleibt es so. Die Tatsache, dass Sie diesset +i
in älteren Bash-Versionen tun konnten, war ein Fehler.bash
, werden Sie wahrscheinlich feststellen, dass es eineinteractive
globale boolesche Variable gibt, die deri
Flagge von zugeordnet ist$-
. Durch Ändern dieses Booleschen Werts werden nicht alle Verhaltensweisen interaktiver Shells automatisch geändert. Der Wechsel von interaktiv zu nicht interaktiv wird nicht unterstützt.set +i
und beendet die Anzeige einer Eingabeaufforderung. Dies ist etwas, das der Benutzer nicht tun soll. Daher ist es nicht verwunderlich, dass das Verhalten von der Shell abhängt und häufig eher zufällig als das Ergebnis einer absichtlichen Entscheidung des Shell-Implementierers ist.