¿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 shell’s 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 sh
definició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 bash
tiene, 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 +i
en 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 +i
y 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_comments
opció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 i
el 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?)
fuente
Respuestas:
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 indicacionesset +m
para deshabilitar el control del trabajozle
y todos los módulos de finalización enzsh
.Pero si desea que el shell deje de ser interactivo, puede hacer lo siguiente:
Para decirle que obtenga el resto de los comandos
/some/file
(reemplácelos con/dev/tty
si 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 comportamientoreturn
o el hecho que todavía haría control de trabajo o: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 +i
regresa con un mebash: set: +i: invalid option
gusta en la mayoría de los otros shells.fuente
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íai
, pero es posible que no lo haga. No estoy seguro de que haya mucho más que discutir al respecto.interactive
, sigue siéndolo. El hecho de que pudieras hacerloset +i
en versiones anteriores de bash era un error.bash
, probablemente encontrará que hay unainteractive
variable booleana global que se asigna a lai
bandera 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.set +i
y 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.