Itu 255
file descriptor adalah pegangan terbuka untuk tty mengendalikan dan hanya digunakan ketika bash
dijalankan dalam modus interaktif.
Ini memungkinkan Anda untuk mengarahkan ulang stderr
di 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, sleep
prosesnya akan kebal terhadap ^ C dan ^ Z, dan harus terbunuh dari jendela / sesi lain. Itu karena shell tidak akan dapat mengatur grup proses sleep
sebagai latar depan di terminal tcsetgrp()
, karena file deskriptor 2 tidak lagi menunjuk ke terminal.
Ini tidak bash
spesifik, ini juga digunakan dalam dash
dan 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 bash
menggunakan 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.
bash
menggunakan jumlah yang sedemikian besar untuk memungkinkan fds lebih besar daripada yang 9
digunakan 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_tty
variabel. 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 stderr
terpasang 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_tty
tty 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]etpgrp
di 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_tty
semua diatur ke close-on-exec, sehingga mereka tidak akan bocor ke perintah.