`tty<&1`と`echo$(tty<&1)`と`echo$(tty<&2)`情報

`tty<&1`と`echo$(tty<&1)`と`echo$(tty<&2)`情報

以下のコードスニペットのメインステートメント(つまり、ラベルの印刷に使用されるステートメントとスペースに使用される空白行を除く)はペアで表示されます。各ペアでは、最初と2番目のステートメントはそれぞれおよびtty...形式ですecho $(tty...)

echo stdin:
tty
echo $(tty)

echo

echo stdout:
tty <&1
echo $(tty <&1)

echo

echo stderr:
tty <&2
echo $(tty <&2)

このコードスニペットを含むファイルをインポートすると(zshORセッションなど)、次の出力が表示されます。1(後で参照用に行番号を追加しました):bash

 1    stdin:
 2    /dev/pts/8
 3    /dev/pts/8
 4    
 5    stdout:
 6    /dev/pts/8
 7    not a tty
 8    
 9    stderr:
10    /dev/pts/8
11    /dev/pts/8

この出力で(ライン7)によって生成されたラインはecho $(tty <&1)2つの理由で顕著です。

  1. echo $(tty ...)tty ...これは、以前に作成された行(2、6、10行)とは異なる唯一の生成された行(つまり、3、7、11行)です。
  2. これは形式的に同様の出力(ライン11)とは異なりますecho $(tty <&2)

尋ねる:これら2つの違いをどのように説明できますか?


記録上、私はこのマニュアルページでこれらの明らかな異常現象の説明を見つけようとしましたが、tty私が知っている限り、そのページはこれらの問題をまったく明示的に扱っていませんでした

この問題はいくつかのコードが原因で発生します。これは素晴らしい答えです前の質問の一つです。


1もちろん/dev/pts/端末を変えれば、その後の実際の数値は変わることがあり、同じことを試しても皆さんには異なることがあります。

2実際にはtty、システムで利用可能なマニュアルページの完全な説明セクションには、「標準入力に接続されている端末のファイル名を印刷してください」という1つの文だけが含まれています。

3ここで私は私よりも多くの背景知識を持つ人がそうする可能性を開いておきます。ミルダtty上記の動作は、簡潔なマニュアルページで確認できます。

答え1

tty(標準出力から)標準入力(fd 0)で開いているttyデバイスの名前を報告します。

存在する:

tty <&2

これはどんな略語ですか?

tty 0<&2

シェルは、fd 0をfd 2で開いたのと同じリソースにリダイレクトします(dup2(2, 0)新しいプロセスでaを実行してからttyそのプロセスで実行)。したがって、ttyfd 0と2に同じリソースがあり、fd 1にttyを作成すると、両方が開いています(存在する場合)。

次のような場合でも同じ状況が発生します。

tty <&1

存在する:

echo "$(tty <&1)"

しかし、このコマンドはパイプに行く fd 1 を置き換えます (そしてシェルはもう一方の端から出力を読み込みます)。これはttyfd 1が行くのとは異なるリソースです。echo

fd 1で開かれたttyを知ってコマンド置換を使用するには、次のものが必要です。

{ echo "$(tty <&3)"; } 3<&1

したがって、実行中のプロセスにはtty次のものがあります。

  • 3: 外層1と同じ
  • 1: パイプ
  • 2: 触れない
  • 0:3と同じなので、外部1と同じ

したがって、tty接続されたttyデバイスのパスはそのパイプに書き込むことができます。外の標準出力。

tty は fd 3 を必要としないので、次のコマンドを使用してより簡潔にすることができます。

{ echo "$(tty <&3 3<&-)"; } 3<&1

つまり、ジョブが終了すると閉じてfd 0にコピーします。

関連情報