Itu 255file descriptor adalah pegangan terbuka untuk tty mengendalikan dan hanya digunakan ketika bashdijalankan dalam modus interaktif.
Ini memungkinkan Anda untuk mengarahkan ulang stderrdi shell utama, sambil tetap memungkinkan kontrol pekerjaan berfungsi (mis. Dapat mematikan proses dengan ^ C, mengganggu mereka dengan ^ Z, dll).
Contoh:
$ exec 2> >(tee /tmp/err); ls /nosuchfile; sleep 1000
Jika Anda mencobanya di shell like ksh93, yang hanya menggunakan file deskriptor 2 sebagai referensi ke terminal pengendali, sleepprosesnya akan kebal terhadap ^ C dan ^ Z, dan harus terbunuh dari jendela / sesi lain. Itu karena shell tidak akan dapat mengatur grup proses sleepsebagai latar depan di terminal tcsetgrp(), karena file deskriptor 2 tidak lagi menunjuk ke terminal.
Ini tidak bashspesifik, ini juga digunakan dalam dashdan zsh, hanya bahwa deskriptor tidak dipindahkan setinggi itu (biasanya 10).
zsh juga akan menggunakan fd itu untuk mengulang permintaan dan input pengguna, jadi cukup yang berikut ini akan berfungsi:
$ exec 2>/tmp/err
$
Ini tidak ada hubungannya dengan menangani file bashmenggunakan ketika membaca skrip dan mengatur pipa (yang juga ditipu keluar dari jalan dengan fungsi yang sama - move_to_high_fd()), seperti yang disarankan dalam jawaban dan komentar lain.
bashmenggunakan jumlah yang sedemikian besar untuk memungkinkan fds lebih besar daripada yang 9digunakan dengan pengalihan in-shell (mis. exec 87<filename); itu tidak didukung di shell lain.
Anda dapat menggunakan file itu menangani sendiri, tetapi ada gunanya melakukannya, karena Anda bisa mendapatkan pegangan ke terminal pengendali yang sama di setiap perintah ... < /dev/tty.
Analisis kode sumber bash :
Dalam bash, deskriptor file dari terminal pengendali disimpan dalam shell_ttyvariabel. Jika shell bersifat interaktif, variabel tersebut diinisialisasi (pada saat startup atau setelah eksekutif yang gagal) masuk jobs.c:initialize_job_control()dengan dup'ing dari stderr(jika stderrterpasang ke terminal) atau dengan langsung membuka /dev/tty, dan kemudian ditiru lagi ke fd yang lebih tinggi dengan 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);
...
}
Jika shell_ttytty belum mengendalikan, maka dibuat demikian:
/* 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 kemudian digunakan untuk
mendapatkan dan mengatur kelompok proses latar depan dengan tc[sg]etpgrpdi jobs.c:maybe_give_terminal_to(), jobs.c:set_job_control()danjobs.c:give_terminal_to()
dapatkan dan atur termios(3)params di jobs.c:get_tty_state()danjobs.c:set_tty_state()
dapatkan ukuran jendela terminal dengan ioctl(TIOCGWINSZ)in lib/sh/winsize.c:get_new_window_size().
move_to_high_fd()umumnya digunakan dengan semua deskriptor file sementara yang digunakan oleh bash(file skrip, pipa, dll), dari sana kebingungan dalam sebagian besar komentar yang muncul secara jelas dalam pencarian google.
Deskriptor file yang digunakan secara internal oleh bash, termasuk shell_ttysemua diatur ke close-on-exec, sehingga mereka tidak akan bocor ke perintah.