Um shell interativo pode se tornar não interativo ou vice-versa?

15

Um shell interativo pode se tornar não interativo ou vice-versa?

Nota: Pesquisei bastante a questão básica "Qual é a diferença entre interativo e não interativo?", E os resultados de minha pesquisa me levaram a fazer essa pergunta.

Esta pergunta tem um preâmbulo longo em parte porque é crucial que tipo de definição usamos para "interativo" para respondê-la. Uma definição pode ser um rótulo arbitrário para um determinado conjunto; pode ser descritivo de várias propriedades; ou pode fornecer informações que você pode usar para prever o comportamento e entender o propósito. Esse último tipo pode ser chamado de "definição de ação" ou "definição dinâmica" e é o mais útil.


Em man 1p sh, é dada a seguinte definição de um shell interativo:

   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.

Com a menção de "-i option" e o uso da palavra "operandos", isso se refere à invocação de um shell , não a atributos que poderiam ser examinados em um shell em execução.

A página de manual do Bash define um pouco de maneira diferente:

   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.

A definição na primeira frase novamente refere-se apenas ao início de um shell.

A segunda frase (na minha leitura) define condições que são usadas como proxies para estabelecer se o shell foi iniciado das maneiras específicas definidas para torná-lo "interativo".

Observe que eu não interpreto esta frase como: "Um shell bash é interativo se e somente se $-incluir 'i'". $-parece ser apenas um indicador útil, não uma definição de interativo. Isso é crucialmente relevante para minha pergunta.


Ambos (a shdefinição POSIX e Bash) são definições mecânicas que informam em que circunstâncias o rótulo "interativo" se aplica a um shell que você iniciou. Eles não são definições de ação , pois não dão implicações a esse rótulo.

No entanto, vejo que em todo o restante da página de manual do Bash são espalhadas referências ao shell se comportando de certas maneiras "a menos que seja um shell interativo" ou "apenas em shells interativos, ou se a opção _____ estiver configurada". (Existem inúmeros exemplos e esse não é o ponto principal desta pergunta.)

Portanto, aceito que "interativo" é apenas um rótulo conveniente para a coleção de comportamentos "interativos" padrão (configurações de opções) descritos em todo o restante da página do manual. Não é um termo ou objeto fundamental em si; não possui definição autoritativa fora do código-fonte do shell. (Diferente, por exemplo, dos termos "descritor de arquivo aberto" ou "processo parado", que se referem a abstrações incorporadas ao design do próprio kernel.)

(Embora também esteja definido na definição de POSIX de sh, essa página de manual [ man 1p sh] tem muito menos usos de "a menos que o shell seja interativo" e de instruções semelhantes que o man bashpossuam, e se concentra quase exclusivamente nas diferenças de tempo de invocação, portanto, focarei no Bash deste ponto em diante.)


Algumas das implicações de um shell ser "interativo" são relevantes apenas no momento da chamada , como quais arquivos são originados pelo shell antes de ler outros comandos. No entanto, não são as implicações (pelo menos em Bash) que são relevantes a qualquer momento. Portanto, deve haver uma maneira de dizer, para qualquer shell em execução , se é interativo ou não.

A execução set +iem um shell Bash interativo faz com que 'i' seja removido do conteúdo de $-.

A pergunta é: isso realmente significa que o shell não é mais interativo?

Pela definição exata de Bash, não deveria, pois em nenhum lugar da definição é necessário que 'i' esteja presente em $-:

   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.

Uma leitura estrita da definição exata também levanta a questão: se o stdin ou stderr de um terminal interativo são redirecionados para que não sejam mais conectados aos terminais, o shell se torna não interativo?

( Parece que a resposta para essa pergunta é "não" e a página de manual poderia ter incluído o modificador: "cuja entrada e erro padrão estão conectados aos terminais ... no momento da invocação " , mas não sei definitivamente.)


Se a resposta for "Não, um shell não pode se tornar não interativo, nem vice-versa", então qual é a maneira definitiva de determinar se o shell é interativo?

Dito de outra maneira: se houver comportamentos de um "shell interativo" que persistem depois set +i, que é usado para determinar que esses comportamentos devem continuar sendo aplicados?


Para que não duvido que alguém que: Não são comportamentos de um shell invocou interativa que persistem após set +ie comportamentos de um shell invocado não interativa que persistem após set -i. Por exemplo, considere o seguinte trecho de 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.

Assim, desabilitando o interactive_comments opção, podemos ver uma diferença entre shells interativos e não interativos. A persistência dessa diferença é demonstrada pelo seguinte 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

Isso confirma que "interativo" e "tem io valor de $-" são não equivalentes.

Um teste semelhante usando ${parameter:?word}um parâmetro não definido produz resultados semelhantes, confirmando novamente que $-não é a "fonte da verdade" para a interatividade do shell.


Então, finalmente, onde está armazenada a característica definitiva de 'interatividade' de um shell?

E, um shell interativo pode se tornar não interativo ou vice-versa? (... alterando essa característica?)

Curinga
fonte
Esta questão também é discutida em algum momento no chat .
Curinga

Respostas:

9

A pergunta que eu faria seria por que alguém iria querer fazer isso?

Você pode desativar alguns aspectos de shells interativos, como:

  • PS1= PS2= desativar os prompts
  • set +m desativar o controle do trabalho
  • desativar histórico em algumas conchas
  • você poderá descarregar o zlee todos os módulos de conclusão zsh.

Mas se você quiser que o shell pare de ser interativo, você pode:

. /some/file; exit

Para dizer a ele para obter o restante dos comandos /some/file(substitua por /dev/ttyse você ainda deseja que os comandos sejam lidos no dispositivo tty), embora ainda existam algumas diferenças em relação aos shells não interativos, como o comportamento returnou o fato que ainda faria o controle do trabalho ou:

exec myshell /dev/tty

Para substituir seu shell interativo atual por um não interativo que ainda lê comandos do dispositivo tty.

Observe que, com o bash 4.4, set +iretorna com um bash: set: +i: invalid optionlike na maioria dos outros shells.

Stéphane Chazelas
fonte
Absolutamente concordado que seria uma coisa ridícula de se fazer. Meu conceito de "interativo", como mencionei, é que é apenas uma coleção de comportamentos padrão que são úteis quando você está interagindo com seu shell. Se você pode alterar cada um desses comportamentos individualmente e alterar cada um deles, a pergunta "Ainda é um shell interativo?" é apenas semântica ridícula; nem sequer é uma pergunta importante. No entanto ...
Wildcard
1
@Wildcard, se você usa exec < <(sleep infinity)um shell interativo, possui um shell interativo que não é muito interativo. O shell ainda se consideraria interativo, $-pois ainda conteria i, mas você talvez não. Não sei se há muito mais a discutir sobre isso.
Stéphane Chazelas
2
@Wildcard, se o shell foi iniciado como interactive, continua sendo. O fato de você poder fazer set +iem versões mais antigas do bash era um bug.
Stéphane Chazelas 23/01
1
@Wildcard, se você olhar para o código fonte de bash, provavelmente encontrará uma interactivevariável booleana global que mapeia para o isinalizador de $-. Alterar esse booleano não mudará automaticamente todos os comportamentos de shells interativos. A mudança de interativo para não interativo não é suportada.
Stéphane Chazelas
4
O @Wildcard Dash aceita set +ie para de exibir um prompt. Isso é algo que o usuário não deve fazer, portanto, não é de surpreender que o comportamento dependa do shell e geralmente seja acidental, e não o resultado de uma decisão deliberada do implementador do shell.
Gilles 'SO- stop be evil'