Kann eine interaktive Shell nicht interaktiv werden oder umgekehrt?

15

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 shwird die folgende Definition einer interaktiven Shell angegeben:

   If the -i option is present, or  if  there  are  no  operands  and  the
   shells  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- shDefinition 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 bashund 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 +iin 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 +iwie 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_commentsOption 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 " iim 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?)

Platzhalter
quelle
Diese Frage wird auch im Chat ausführlich diskutiert .
Wildcard

Antworten:

9

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 deaktivieren
  • set +m um die Jobsteuerung zu deaktivieren
  • Deaktivieren Sie den Verlauf in einigen Shells
  • Möglicherweise können Sie das zleund alle Completion-Module in entladen zsh.

Wenn Sie jedoch möchten, dass die Shell nicht mehr interaktiv ist, können Sie stattdessen Folgendes tun:

. /some/file; exit

Zu sagen, dass es den Rest der Befehle erhalten soll /some/file(ersetzen durch, /dev/ttywenn 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 von returnoder die Tatsache dass es immer noch Jobkontrolle machen würde oder:

exec myshell /dev/tty

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 +iein bash: set: +i: invalid optionähnliches Ergebnis erzielt wird .

Stéphane Chazelas
quelle
Absolut einverstanden wäre es eine lächerliche Sache zu tun. Mein Konzept von "interaktiv" ist, wie ich bereits erwähnte, dass es sich nur um eine Sammlung von Standardverhalten handelt, die nützlich sind, wenn Sie mit Ihrer Shell interagieren . Wenn Sie jedes dieser Verhaltensweisen einzeln ändern können und Sie dies auch tun, stellt sich die Frage "Ist es immer noch eine interaktive Shell?". ist nur lächerliche Semantik; Es ist nicht einmal eine wichtige Frage. Allerdings ....
Wildcard
1
@Wildcard, wenn Sie 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 enthalten i, aber Sie könnten nicht. Ich bin mir nicht sicher, ob es noch viel mehr zu besprechen gibt.
Stéphane Chazelas
2
@Wildcard, wenn die Shell als gestartet wurde interactive, bleibt es so. Die Tatsache, dass Sie dies set +iin älteren Bash-Versionen tun konnten, war ein Fehler.
Stéphane Chazelas
1
@Wildcard, Wenn Sie sich den Quellcode von ansehen bash, werden Sie wahrscheinlich feststellen, dass es eine interactiveglobale boolesche Variable gibt, die der iFlagge 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.
Stéphane Chazelas
4
@Wildcard Dash akzeptiert set +iund 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.
Gilles 'SO- hör auf böse zu sein'