Ese 255
descriptor de archivo es un identificador abierto para el tty de control y solo se usa cuando bash
se ejecuta en modo interactivo.
Le permite redirigir stderr
en el shell principal, al tiempo que permite que el control de trabajo funcione (es decir, poder matar procesos con ^ C, interrumpirlos con ^ Z, etc.).
Ejemplo:
$ exec 2> >(tee /tmp/err); ls /nosuchfile; sleep 1000
Si intenta eso en un shell como ksh93
, que simplemente usa el descriptor de archivo 2 como referencia al terminal de control, el sleep
proceso se volverá inmune a ^ C y ^ Z, y tendrá que ser eliminado desde otra ventana / sesión. Esto se debe a que el shell no podrá establecer el grupo de procesos sleep
como primer plano en el terminal tcsetgrp()
, ya que el descriptor de archivo 2 ya no apunta al terminal.
Esto no es bash
específico, también se usa dash
y zsh
, solo que el descriptor no se mueve tan alto (generalmente es 10).
zsh
también usará esa fd para hacer eco de las indicaciones y la entrada del usuario, por lo que simplemente funcionará lo siguiente:
$ exec 2>/tmp/err
$
No tiene nada que ver con los identificadores de archivos que bash
se utilizan al leer secuencias de comandos y configurar tuberías (que también se duplican con la misma función move_to_high_fd()
), como se sugirió en otras respuestas y comentarios.
bash
está utilizando un número tan grande para permitir que los fds sean más grandes que 9
para ser utilizados con redireccionamientos en shell (por ejemplo exec 87<filename
); eso no es compatible con otros proyectiles.
Puede usar ese identificador de archivo usted mismo, pero no tiene mucho sentido hacerlo, porque puede obtener un identificador para el mismo terminal de control en cualquier comando con ... < /dev/tty
.
Análisis del código fuente de bash :
En bash
, el descriptor de archivo del terminal de control se almacena en la shell_tty
variable. Si el shell es interactivo, esa variable se inicializa (al inicio o después de un exec fallido) jobs.c:initialize_job_control()
al duplicarla desde stderr
(si stderr
está conectada a un terminal) o al abrirla directamente /dev/tty
, y luego se duplica nuevamente a un fd más alto con general.c:move_to_high_fd()
:
int
initialize_job_control (force)
int force;
{
...
if (interactive == 0 && force == 0)
{
...
}
else
{
shell_tty = -1;
/* If forced_interactive is set, we skip the normal check that stderr
is attached to a tty, so we need to check here. If it's not, we
need to see whether we have a controlling tty by opening /dev/tty,
since trying to use job control tty pgrp manipulations on a non-tty
is going to fail. */
if (forced_interactive && isatty (fileno (stderr)) == 0)
shell_tty = open ("/dev/tty", O_RDWR|O_NONBLOCK);
/* Get our controlling terminal. If job_control is set, or
interactive is set, then this is an interactive shell no
matter where fd 2 is directed. */
if (shell_tty == -1)
shell_tty = dup (fileno (stderr)); /* fd 2 */
if (shell_tty != -1)
shell_tty = move_to_high_fd (shell_tty, 1, -1);
...
}
Si aún shell_tty
no es el tty controlador, entonces se hace así:
/* If (and only if) we just set our process group to our pid,
thereby becoming a process group leader, and the terminal
is not in the same process group as our (new) process group,
then set the terminal's process group to our (new) process
group. If that fails, set our process group back to what it
was originally (so we can still read from the terminal) and
turn off job control. */
if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
{
if (give_terminal_to (shell_pgrp, 0) < 0)
shell_tty
entonces se usa para
obtener y establecer el grupo de procesos en primer plano con tc[sg]etpgrp
in jobs.c:maybe_give_terminal_to()
, jobs.c:set_job_control()
yjobs.c:give_terminal_to()
obtener y establecer los termios(3)
parámetros en jobs.c:get_tty_state()
yjobs.c:set_tty_state()
obtener el tamaño de la ventana de terminal con ioctl(TIOCGWINSZ)
in lib/sh/winsize.c:get_new_window_size()
.
move_to_high_fd()
generalmente se usa con todos los descriptores de archivos temporales utilizados por bash
(archivos de script, tuberías, etc.), de ahí la confusión en la mayoría de los comentarios que aparecen de manera prominente en las búsquedas de Google.
Los descriptores de archivo utilizados internamente por bash
, incluidos, shell_tty
están configurados en close-on-exec, por lo que no se filtrarán a los comandos.