その255ファイル記述子は、制御ttyへのオープンハンドルであり、bashがインタラクティブモードで実行されている場合にのみ使用されます。
stderrメインシェルでをリダイレクトしながら、ジョブ制御を機能させます(つまり、^ Cでプロセスを強制終了したり、^ Zでプロセスを中断したりすることができます)。
例:
$ exec 2> >(tee /tmp/err); ls /nosuchfile; sleep 1000
ksh93制御ターミナルへの参照としてファイル記述子2を使用しているだけのようなシェルでそれを試すと、sleepプロセスは^ Cおよび^ Zの影響を受けなくなり、別のウィンドウ/セッションから強制終了する必要があります。これは、ファイル記述子2がもはやターミナルを指していないため、シェルはのプロセスグループをsleepターミナルでフォアグラウンドのプロセスグループとして設定できないtcsetgrp()ためです。
これはbash特定のものではなく、dashおよびでも使用されzshます。記述子がそれほど高く移動されないことだけです(通常は10です)。
zsh また、そのfdを使用してプロンプトとユーザー入力をエコーするので、次のように機能します。
$ exec 2>/tmp/err
$
他の回答やコメントで提案されてbashいるように、スクリプトを読み取ったりパイプを設定したりするときに使用するファイルハンドル(同じ機能で邪魔にならない-)とは関係ありませんmove_to_high_fd()。
bash9シェル内リダイレクト(たとえばexec 87<filename)で使用されるよりも大きいfdsを許可するために、このような大きな数を使用しています。他のシェルではサポートされていません。
このファイルハンドルは自分で使用できますが、を使用すると、どのコマンドでも同じ制御端末へのハンドルを取得できるので、そうする意味がほとんどありません... < /dev/tty。
bashのソースコード分析:
ではbash、制御端末のファイル記述子がshell_tty変数に格納されます。シェルが対話型である場合、その変数は、中(起動時または失敗EXECの後に)初期化されるjobs.c:initialize_job_control()からそれをdup'ingによってstderr(場合stderr、端末に装着される)または直接開いて/dev/tty、その後より高いFDに再度dup'edれますと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);
...
}
shell_ttyが制御ttyでない場合は、次のように作成されます。
/* 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 次に使用されます
取得してフォアグラウンドプロセスグループを設定tc[sg]etpgrp中jobs.c:maybe_give_terminal_to()、jobs.c:set_job_control()およびjobs.c:give_terminal_to()
取得および設定termios(3)中のparamsをjobs.c:get_tty_state()し、jobs.c:set_tty_state()
ターミナルウィンドウのサイズを取得ioctl(TIOCGWINSZ)の中でlib/sh/winsize.c:get_new_window_size()。
move_to_high_fd()通常は、bash(スクリプトファイル、パイプなど)が使用するすべての一時ファイル記述子で使用されます。そのため、Google検索で目立つように表示されるほとんどのコメントで混乱が生じます。
bashを含め、内部で使用されるファイル記述子shell_ttyはすべてclose-on-execに設定されているため、コマンドにリークされることはありません。