Una shell interattiva può diventare non interattiva o viceversa?


15

Una shell interattiva può diventare non interattiva o viceversa?

Nota: ho fatto molte ricerche sulla domanda di base, "Qual è la differenza tra interattivo e non interattivo?", E i risultati della mia ricerca mi hanno portato a porre questa domanda.

Questa domanda ha in parte un lungo preambolo perché è cruciale quale tipo di definizione utilizziamo per "interattivo" per rispondere. Una definizione potrebbe essere un'etichetta arbitraria per un determinato set; potrebbe essere descrittivo di varie proprietà; o può darti informazioni che puoi usare per prevedere il comportamento e capire lo scopo. Quest'ultimo tipo possiamo chiamare una "definizione di azione" o una "definizione dinamica" ed è la più utile.


In man 1p sh, viene fornita la seguente definizione di shell interattiva:

   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.

Dalla menzione di "opzione -i" e dall'uso della parola "operandi", questo si riferisce all'invocazione di una shell , non ad attributi che potrebbero essere esaminati in una shell in esecuzione.

La pagina man di Bash la esprime in modo leggermente diverso:

   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.

La definizione nella prima frase si riferisce ancora solo all'inizio di una shell.

La seconda frase (nella mia lettura) definisce le condizioni che vengono utilizzate come proxy per stabilire se la shell è stata avviata nei modi particolari definiti come "interattivi".

Si noti che io non interpreto questa frase come: "shell bash è interattiva A se e solo se $-. Include 'i'" $-sembra essere solo un utile indicatore, non una definizione di interattivo. Questo è di fondamentale importanza per la mia domanda.


Entrambi (la shdefinizione POSIX e quella di Bash) sono definizioni meccaniche che indicano in quali circostanze l'etichetta "interattivo" si applica a una shell che hai avviato. Non sono definizioni di azione in quanto non danno implicazioni a questa etichetta.

Tuttavia, vedo che in tutto il resto della pagina man di Bash sono presenti dei riferimenti sparsi alla shell che si comportano in determinati modi "a meno che non sia una shell interattiva" o "solo nelle shell interattive o se è impostata l'opzione _____". (Ci sono numerosi esempi e non è questo il punto principale di questa domanda.)

Quindi accetterò che "interattivo" è solo un'etichetta conveniente per la raccolta di comportamenti "interattivi" predefiniti (impostazioni delle opzioni) descritti nel resto della pagina man. Non è un termine o un oggetto fondamentale in sé; non ha una definizione autorevole al di fuori del codice sorgente della shell. (A differenza, ad esempio, dei termini "descrittore di file aperto" o "processo arrestato" che si riferiscono alle astrazioni incorporate nella progettazione del kernel stesso.)

(Sebbene sia anche definito nella definizione POSIX di sh, quella pagina man [ man 1p sh] ha molti meno usi di "a meno che la shell non sia interattiva" e dichiarazioni simili rispetto a quelle che man bashha, e si concentra quasi esclusivamente sulle differenze di tempo di invocazione, quindi mi concentrerò su Bash da questo punto in poi.)


Alcune delle implicazioni di una shell come "interattiva" sono comunque rilevanti solo al momento dell'invocazione , come ad esempio quali file provengono dalla shell prima che legga altri comandi. Tuttavia, ci sono implicazioni (almeno in Bash) che sono rilevanti in qualsiasi momento. Quindi deve esserci un modo per dire, per ogni data shell in esecuzione , se è interattiva o no.

L'esecuzione set +iin una shell Bash interattiva comporta la rimozione di 'i' dal contenuto di $-.

La domanda è: questo significa che la shell non è più interattiva?

Secondo l'esatta definizione di Bash, non dovrebbe, poiché in nessuna parte della definizione è richiesto che 'i' sia presente 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.

Una lettura rigorosa della definizione esatta solleva anche la domanda: se lo stdin o lo stderr di un terminale interattivo vengono reindirizzati in modo che non siano più collegati ai terminali, la shell diventa non interattiva?

( Sembra che la risposta a questa sia "no" e la pagina man avrebbe potuto includere il modificatore: "i cui input ed errori standard sono entrambi collegati ai terminali ... al momento dell'invocazione " , ma non lo so definitivamente.)


Se la risposta è "No, una shell non può diventare non interattiva, né viceversa", qual è il modo definitivo per determinare se la shell è interattiva?

Detto in altro modo: se ci sono comportamenti di una "shell interattiva" che persistono dopo set +i, a che cosa serve determinare che tali comportamenti dovrebbero continuare ad applicarsi?


Perché nessuno ne dubiti: ci sono comportamenti di una shell invocati in modo interattivo che persistono dopo set +ie comportamenti di una shell invocati in modo non interattivo che persistono dopo set -i. Per un esempio, considera il seguente estratto da 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.

Quindi, disabilitando l' interactive_commentsopzione, possiamo vedere una differenza tra shell interattive e non interattive. La persistenza di questa differenza è dimostrata dal seguente script:

#!/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

Ciò conferma che "interattivo" e "ha inel valore di $-" non sono equivalenti.

Un test simile che utilizza ${parameter:?word}un parametro non impostato produce risultati simili, confermando ancora una volta che $-non è la "fonte di verità" per l'interattività della shell.


Quindi, infine, dove è memorizzato il tratto definitivo di "interattività" di una shell?

E una shell interattiva può diventare non interattiva o viceversa? (... cambiando questo tratto?)


Risposte:


9

La domanda che vorrei porre è: perché qualcuno vorrebbe farlo?

Puoi disabilitare alcuni aspetti delle shell interattive come:

  • PS1= PS2= per disabilitare le istruzioni
  • set +m per disabilitare il controllo del lavoro
  • disabilita la cronologia in alcune shell
  • potresti essere in grado di scaricare il zlee tutti i moduli di completamento in zsh.

Ma se vuoi che la shell smetta di essere interattiva, puoi invece fare:

. /some/file; exit

Per dirgli di ottenere il resto dei comandi /some/file(sostituirlo con /dev/ttyse si desidera ancora che i comandi vengano letti dal dispositivo tty), anche se ci sarebbero ancora alcune differenze rispetto alle shell non interattive, come per il comportamento returno il fatto che avrebbe comunque fatto il controllo del lavoro o:

exec myshell /dev/tty

Per sostituire l'attuale shell interattiva con una non interattiva che legge ancora i comandi dal dispositivo tty.

Nota che con bash 4.4, set +iritorna con un bash: set: +i: invalid optionlike nella maggior parte delle altre shell.


Assolutamente d'accordo che sarebbe una cosa ridicola da fare. Il mio concetto di "interattivo", come ho già detto, è che è solo una raccolta di comportamenti predefiniti che sono utili quando si interagisce con la shell. Se riesci a cambiare ognuno di questi comportamenti singolarmente e cambi ognuno di loro, allora la domanda "È ancora una shell interattiva?" è solo una semantica ridicola; non è nemmeno una domanda importante. Tuttavia ....
Wildcard il

1
@Wildcard, se lo fai exec < <(sleep infinity)in una shell interattiva, hai una shell interattiva che non è molto interattiva. La shell si considererebbe comunque interattiva in quanto $-conterrebbe ancora i, ma potresti non farlo. Non sono sicuro che ci sia molto altro da discutere al riguardo.
Stéphane Chazelas,

2
@Wildcard, se la shell è stata avviata come interactive, rimane tale. Il fatto che si potesse fare set +inelle versioni bash precedenti era un bug.
Stéphane Chazelas,

1
@Wildcard, Se guardi il codice sorgente di bash, probabilmente troverai una interactivevariabile booleana globale che si associa alla ibandiera di $-. Cambiare quel booleano non cambierà automaticamente tutti i comportamenti delle shell interattive. Il passaggio da interattivo a non interattivo non è supportato.
Stéphane Chazelas,

4
@Wildcard Dash accetta set +ie interrompe la visualizzazione di un prompt. Questo è qualcosa che l'utente non dovrebbe fare, quindi non sorprende che il comportamento dipenda dalla shell ed è spesso accidentale piuttosto che il risultato di una decisione deliberata da parte dell'implementatore della shell.
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.