¿Puede un shell interactivo volverse no interactivo o viceversa?

15

¿Puede un shell interactivo volverse no interactivo o viceversa?

Nota: He investigado mucho sobre la pregunta básica, "¿Cuál es la diferencia entre interactivo y no interactivo?", Y los resultados de mi investigación me llevaron a hacer esta pregunta.

Esta pregunta tiene un largo preámbulo en parte porque es crucial qué tipo de definición usamos para "interactiva" para responderla. Una definición podría ser una etiqueta arbitraria para un determinado conjunto; podría ser descriptivo de varias propiedades; o puede darle información que puede usar para predecir el comportamiento y comprender el propósito. Este último tipo lo podemos llamar "definición de acción" o "definición dinámica" y es el más útil.


En man 1p sh, se proporciona la siguiente definición de un shell interactivo:

   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.

Por la mención de "opción -i" y el uso de la palabra "operandos", esto se refiere a la invocación de un shell , no a los atributos que podrían examinarse en un shell en ejecución.

La página de manual de Bash lo expresa un poco 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.

La definición en la primera oración nuevamente solo se refiere al comienzo de un shell.

La segunda oración (en mi lectura) define las condiciones que se utilizan como proxies para establecer si el shell se inició en las formas particulares que se definen como hacerlo "interactivo".

Tenga en cuenta que yo no interpreto esta frase como: "shell bash es una interactiva si y sólo si $-incluye 'i'." $-parece ser solo un indicador útil, no un definición de interactivo. Esto es crucialmente relevante para mi pregunta.


Ambas (la shdefinición de POSIX y la de Bash) son definiciones mecánicas que indican en qué circunstancias la etiqueta "interactivo" se aplica a un shell que ha comenzado. No son definiciones de acción, ya que no dan ninguna implicación de esta etiqueta.

Sin embargo, veo que en el resto de la página del manual de Bash hay referencias dispersas al shell que se comporta de ciertas maneras "a menos que sea un shell interactivo" o "solo en shells interactivos, o si la opción _____ está configurada". (Existen numerosos ejemplos y ese no es el punto principal de esta pregunta).

Así que aceptaré que "interactivo" es solo una etiqueta conveniente para la recopilación de comportamientos "interactivos" predeterminados (configuración de opciones) descritos en el resto de la página del manual. No es un término u objeto fundamental en sí mismo; no tiene una definición autorizada fuera del código fuente del shell. (A diferencia, por ejemplo, de los términos "descriptor de archivo abierto" o "proceso detenido" que se refieren a abstracciones integradas en el diseño del núcleo mismo).

(Si bien también se define en la definición POSIX de sh, esa página de manual [ man 1p sh] tiene muchos menos usos de "a menos que el shell sea interactivo" y declaraciones similares a las que man bashtiene, y se centra casi exclusivamente en las diferencias de tiempo de invocación, por lo que me centraré en Bash desde este punto en adelante)


De todos modos, algunas de las implicaciones de que un shell sea "interactivo" solo son relevantes en el momento de la invocación , como qué archivos obtiene el shell antes de que lea otros comandos. Sin embargo, no son consecuencias (por lo menos en Bash) que son relevantes en cualquier momento. Por lo tanto, debe haber una manera de saber, para cualquier carrera dada shell en , si es interactivo o no.

La ejecución set +ien un shell Bash interactivo hace que 'i' se elimine del contenido de$- .

La pregunta es: ¿Esto realmente significa que el shell ya no es interactivo?

Según la definición exacta de Bash, no debería, ya que en ninguna parte de la definición se requiere que 'i' esté presente en $-:

   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 lectura estricta de la definición exacta también plantea la pregunta: si el stdin o stderr de un terminal interactivo se redirige para que ya no estén conectados a los terminales, ¿el shell deja de ser interactivo?

( Parece que la respuesta a esta pregunta es "no" y la página del manual podría haber incluido el modificador: "cuya entrada estándar y error están conectados a terminales ... en el momento de la invocación " , pero no sé definitivamente)


Si la respuesta es: "No, un shell no puede volverse no interactivo, ni viceversa", ¿ cuál es la forma definitiva de determinar si el shell es interactivo?

Dicho de otra manera: si hay comportamientos de un "caparazón interactivo" que persisten después set +i, ¿qué se usa para determinar que esos comportamientos deberían seguir aplicándose?


Para que nadie lo dude: hay comportamientos de un shell invocado de forma interactiva que persisten después set +iy comportamientos de un shell invocado de forma no interactiva que persisten después set -i. Por ejemplo, considere el siguiente extracto 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.

Por lo tanto, al desmarcar la interactive_commentsopción podemos ver una diferencia entre shells interactivos y no interactivos. La persistencia de esta diferencia se demuestra con el siguiente 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

Esto confirma que "interactivo" y "tiene iel valor de $-" no son equivalentes.

Una prueba similar que se usa ${parameter:?word}con un parámetro no establecido produce resultados similares, confirmando nuevamente que esa $-no es la "fuente de la verdad" para la interactividad del shell.


Así que finalmente, dónde está almacenado el rasgo definitivo de 'interactividad' de un shell?

Y, ¿ puede un shell interactivo volverse no interactivo o viceversa? (... al cambiar este rasgo?)

Comodín
fuente

Respuestas:

9

La pregunta que haría sería por qué alguien querría hacer eso.

Puede deshabilitar algunos aspectos de los shells interactivos como:

  • PS1= PS2= para deshabilitar las indicaciones
  • set +m para deshabilitar el control del trabajo
  • desactivar el historial en algunos shells
  • es posible que pueda descargar el zley todos los módulos de finalización en zsh.

Pero si desea que el shell deje de ser interactivo, puede hacer lo siguiente:

. /some/file; exit

Para decirle que obtenga el resto de los comandos /some/file(reemplácelos con /dev/ttysi aún desea que los comandos se lean desde el dispositivo tty), aunque todavía habría algunas diferencias con los shells no interactivos, como el comportamiento returno el hecho que todavía haría control de trabajo o:

exec myshell /dev/tty

Para reemplazar su actual shell interactivo con uno no interactivo que aún lee comandos del dispositivo tty.

Tenga en cuenta que con bash 4.4, set +iregresa con un me bash: set: +i: invalid optiongusta en la mayoría de los otros shells.

Stéphane Chazelas
fuente
Absolutamente de acuerdo, sería algo ridículo . Mi concepto de "interactivo", como mencioné, es que es solo una colección de comportamientos predeterminados que son útiles cuando interactúa con su shell. Si puede cambiar cada uno de esos comportamientos individualmente, y cambia cada uno de ellos, entonces la pregunta "¿Sigue siendo un shell interactivo?" es simplemente una semántica ridícula; Ni siquiera es una pregunta importante. Sin embargo ....
Comodín
1
@Wildcard, si lo hace exec < <(sleep infinity)en un shell interactivo, tiene un shell interactivo que no es muy interactivo. El shell aún se consideraría interactivo ya que $-aún lo contendría i, pero es posible que no lo haga. No estoy seguro de que haya mucho más que discutir al respecto.
Stéphane Chazelas
2
@Wildcard, si el shell se inició como interactive, sigue siéndolo. El hecho de que pudieras hacerlo set +ien versiones anteriores de bash era un error.
Stéphane Chazelas
1
@Wildcard, si observa el código fuente de bash, probablemente encontrará que hay una interactivevariable booleana global que se asigna a la ibandera de $-. Cambiar ese booleano no cambiará automáticamente todos los comportamientos de los shells interactivos. No se admite el cambio de interactivo a no interactivo.
Stéphane Chazelas
44
@Wildcard Dash acepta set +iy deja de mostrar una solicitud. Esto es algo que se supone que el usuario no debe hacer, por lo que no es sorprendente que el comportamiento dependa del shell y, a menudo, sea accidental más que el resultado de una decisión deliberada del implementador del shell.
Gilles 'SO- deja de ser malvado'