Dieser 255Dateideskriptor ist ein offenes Handle für das steuernde tty und wird nur verwendet, wenn er bashim interaktiven Modus ausgeführt wird.
Sie können das stderrin der Haupt-Shell umleiten , während die Jobsteuerung weiterhin funktioniert (dh Prozesse mit ^ C beenden, mit ^ Z unterbrechen usw.).
Beispiel:
$ exec 2> >(tee /tmp/err); ls /nosuchfile; sleep 1000
Wenn Sie dies in einer Shell wie versuchen ksh93, die einfach den Dateideskriptor 2 als Referenz für das steuernde Terminal verwendet, wird der sleepProzess immun gegen ^ C und ^ Z und muss aus einem anderen Fenster / einer anderen Sitzung beendet werden. Dies liegt daran, dass die Shell die Prozessgruppe von nicht sleepals Vordergrundgruppe im Terminal mit festlegen kann tcsetgrp(), da der Dateideskriptor 2 nicht mehr auf das Terminal zeigt.
Dies ist nicht bashspezifisch, es wird auch in dashund verwendet zsh, nur dass der Deskriptor nicht so hoch verschoben wird (normalerweise sind es 10).
zsh wird dieses fd auch verwenden, um Eingabeaufforderungen und Benutzereingaben wiederzugeben, sodass einfach Folgendes funktioniert:
$ exec 2>/tmp/err
$
Es hat nichts mit den bashDateihandles zu tun, die beim Lesen von Skripten und beim Einrichten von Pipes verwendet werden (die mit derselben Funktion ebenfalls aus dem Weg geräumt werden - move_to_high_fd()), wie dies in anderen Antworten und Kommentaren vorgeschlagen wurde.
bashverwendet eine so große Anzahl, um zu ermöglichen, dass fds größer sind als 9bei In-Shell-Umleitungen (z. B. exec 87<filename); Das wird in anderen Shells nicht unterstützt.
Sie können dieses Dateihandle selbst verwenden, aber es macht wenig Sinn, dies zu tun, da Sie in jedem Befehl mit ein Handle für dasselbe steuernde Terminal erhalten können ... < /dev/tty.
Quellcode-Analyse von Bash :
In bashwird der Dateideskriptor des steuernden Terminals in der shell_ttyVariablen gespeichert . Wenn die Shell interaktiv ist, wird diese Variable (beim Start oder nach einer fehlgeschlagenen Ausführung) jobs.c:initialize_job_control()durch Dup'ing von stderr(wenn stderran ein Terminal angeschlossen) oder durch direktes Öffnen /dev/ttyinitialisiert und dann erneut auf einen höheren fd dup'ed mit 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);
...
}
Wenn shell_ttynicht bereits die steuernde tty ist, dann wird es so gemacht:
/* 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 ist dann daran gewöhnt
Holen und setzen Sie die Vordergrundprozessgruppe mit tc[sg]etpgrpin jobs.c:maybe_give_terminal_to(), jobs.c:set_job_control()undjobs.c:give_terminal_to()
termios(3)Holen Sie sich und setzen Sie die Parameter in jobs.c:get_tty_state()undjobs.c:set_tty_state()
Holen Sie sich die Größe des Terminalfensters mit ioctl(TIOCGWINSZ)in lib/sh/winsize.c:get_new_window_size().
move_to_high_fd()wird im Allgemeinen mit allen temporären Dateideskriptoren verwendet, die von bash(Skriptdateien, Pipes usw.) verwendet werden, daher die Verwirrung in den meisten Kommentaren, die bei Google-Suchanfragen häufig vorkommen.
Die intern von basheinschließlich verwendeten Dateideskriptoren shell_ttysind alle auf close-on-exec eingestellt, damit sie nicht an Befehle weitergegeben werden.