スクリプト内の「3>&1 1>&2 2>&3」は何をしますか?

スクリプト内の「3>&1 1>&2 2>&3」は何をしますか?

スクリプトで次の行を見ました:

DEVICE=`dialog --inputbox "Festplatten-Laufzeit auslesen. Gebe Sie das 
gewünschte Device an: " 0 70 "" 3>&1 1>&2 2>&3`

とは

3>&1 1>&2 2>&3

何をしているのですか? 1 = stdout、2 = stderr であることはわかっていますが、3と は何のために使用される&のでしょうか?

答え1

数字はファイル記述子であり、最初の 3 つ (0 から始まる) のみが標準化された意味を持ちます。

0 - stdin
1 - stdout
2 - stderr

コマンド内のこれらの数字はそれぞれファイル記述子を参照します。ファイル記述子をファイルにリダイレクトする>か、別のファイル記述子にリダイレクトすることができます。>&

3>&1コマンドラインの は新しいファイル記述子を作成し、 にリダイレクトします。1次にSTDOUT、 は1>&2ファイル記述子 1 を にリダイレクトしSTDERR2>&3ファイル記述子 2 を 3 にリダイレクトしますSTDOUT

つまり、基本的には、STDOUTと を切り替えたことSTDERRになります。手順は次のとおりです。

  1. 新しいfd 3を作成し、それをfd 1にポイントします。
  2. ファイル記述子 1 をファイル記述子 2 にリダイレクトします。ファイル記述子を 3 に保存していなければ、ターゲットは失われます。
  3. ファイル記述子 2 をファイル記述子 3 にリダイレクトします。これで、ファイル記述子 1 と 2 が入れ替わります。

これで、プログラムがファイル記述子 1 に何かを印刷すると、ファイル記述子 2 にも印刷され、その逆も同様になります。

答え2

スワッピングstdoutstderr

>name出力をファイルにリダイレクトすることを意味しますname

>&number出力をファイル記述子にリダイレクトすることを意味しますnumber

したがって、&ファイル名ではなくファイル記述子を意味していることをシェルに伝えるために が必要です。

ファイル記述子は、すでに開いているファイルを参照する番号です。標準的なものは、0標準入力、1標準出力、または2標準エラー用です。他の番号を使用して、 で新しい変数を作成するときと同じように、新しいファイル記述子を作成することもできますvar=value

デフォルトでは、ファイル記述子1との両方が2に移動する/dev/ttyため、新しいシェルで実行してもsomecommand 3>&1 1>&2 2>&3何も変更されません (ただし、ファイル記述子番号が 3 になる点が異なります)。

しかし、スクリプトの前のどこかで exec を使用してリダイレクトを行う場合 (例exec 2>error.log)、またはスクリプトがリダイレクトを含むコマンド ラインで実行される場合 (例./thescript 2>error.log)、stdout と stderr を交換すると何かが起こります。

あなたの場合、stdoutとstderrが入れ替わっているコマンドは ですdialog。そのマニュアルページ、 なるほど

Some widgets, e.g., checklist, will write text to dialog's output.
Normally that is the standard error

おそらくスクリプトを書いた人は、何らかの理由で のdialog出力をstdoutではなくに送信したいのでしょう。stderr

参照リダイレクトの順序

答え3

スクリプト作成者は fd 3 を次のように定義しました。

exec 3<> File.txt

「File.txt」を開き、fd 3 を割り当てます。最大ファイル記述子: 255

read -n 4 <&3

4文字のみ読み取ります。

echo -n . >&3

そこに小数点を書いてください。

exec 3>&-

fd 3 を閉じます。

cat File.txt

==> 1234.67890

答え4

以下の例から、ファイル記述子と「3> & 1 1> & 2 2> & 3」コマンドの目的を理解しました。

#!/bin/bash
#it's normal case fd environment

echo test 1> afile.txt
echo "Test no 1"
cat afile.txt
echo "Test no 1"

echo test 2> afile.txt
echo "Test no 2"
cat afile.txt
echo "Test no 2"

echo test 1> afile.txt
echo "Test no 3"
cat afile.txt
echo "Test no 3"
echo test 2> afile.txt

echo "Test no 4"
cat afile.txt
echo "Test no 4"
echo > afile.txt

echo "------------------------------------------------------------------------"

#it's relocate filedescriptor and cause not problem, and cause error(std error)

var=
var=$(echo test 3>&1 1>&2 2>&3)

echo "Test no 5"
#cat afile.txt
echo $var
echo "Test no 5"

var=
var=$(echo test 3>&1 1>&2 2>&3)

echo "Test no 6"
#cat afile.txt
echo $var
echo "Test no 6"

var=
var=$(echo test 3>&1 1>&2 2>&3)

echo "Test no 7"
#cat afile.txt
echo $var
echo "Test no 7"

var=
var=$(echo test 3>&1 1>&2 2>&3)

echo "Test no 8"
#cat afile.txt
echo $var
echo "Test no 8"

この例を実行すると、ファイル記述子が再配置され、出力が変化することがわかります。

関連情報