Was macht "3>&1 1>&2 2>&3" in einem Skript?

Was macht "3>&1 1>&2 2>&3" in einem Skript?

Ich habe diese Zeile in einem Skript gesehen:

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

Was ist

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

machen? Ich weiß, dass 1 = stdout und 2 = stderr, aber wofür sind das 3und das &?

Antwort1

Die Zahlen sind Dateideskriptoren und nur die ersten drei (beginnend mit Null) haben eine standardisierte Bedeutung:

0 - stdin
1 - stdout
2 - stderr

Jede dieser Zahlen in Ihrem Befehl bezieht sich also auf einen Dateideskriptor. Sie können einen Dateideskriptor entweder auf eine Datei umleiten mit >oder auf einen anderen Dateideskriptor mit>&

Das 3>&1in Ihrer Befehlszeile erstellt einen neuen Dateideskriptor und leitet ihn um 1zu STDOUT. Jetzt 1>&2wird der Dateideskriptor 1 umgeleitet zu STDERRund 2>&3der Dateideskriptor 2 wird umgeleitet zu 3 , was ist STDOUT.

Sie haben also im Wesentlichen gewechselt STDOUT. STDERRDies sind die Schritte:

  1. Erstellen Sie ein neues FD 3 und verweisen Sie es auf FD 1
  2. Leiten Sie den Dateideskriptor 1 zum Dateideskriptor 2 um. Wenn wir den Dateideskriptor 3 nicht gespeichert hätten, würden wir das Ziel verlieren.
  3. Leiten Sie Dateideskriptor 2 auf Dateideskriptor 3 um. Jetzt sind Dateideskriptor eins und zwei vertauscht.

Wenn das Programm jetzt etwas in den Dateideskriptor 1 druckt, wird es in den Dateideskriptor 2 gedruckt und umgekehrt.

Antwort2

Es ist ein Austausch stdoutund stderr.

>namebedeutet, die Ausgabe in eine Datei umzuleiten name.

>&numberbedeutet, die Ausgabe zum Dateideskriptor umzuleiten number.

Daher &müssen Sie der Shell mitteilen, dass Sie einen Dateideskriptor und keinen Dateinamen meinen.

Ein Dateideskriptor ist eine Nummer, die sich auf eine bereits geöffnete Datei bezieht. Die Standarddeskriptoren sind 0für die Standardeingabe, 1die Standardausgabe oder 2die Standardfehlerausgabe. Sie können auch jede andere Nummer verwenden, die einen neuen Dateideskriptor erstellt, genau wie wenn Sie mit eine neue Variable erstellen var=value.

Standardmäßig gehen sowohl der Dateideskriptor 1als auch 2zu /dev/tty. Wenn Sie es also in einer neuen Shell ausführen somecommand 3>&1 1>&2 2>&3, ändert sich nichts (außer, dass Sie jetzt einen Dateideskriptor mit der Nummer 3 haben).

Wenn jedoch irgendwo früher im Skript eine Umleitung mit exec erfolgt (z. B. exec 2>error.log) oder das Skript mit einer Befehlszeile einschließlich Umleitung ausgeführt wird (z. B. ./thescript 2>error.log), dann bewirkt das Vertauschen von stdout und stderr etwas.

In Ihrem speziellen Fall ist der Befehl, dessen stdout und stderr vertauscht sind dialog, . Wenn man sich seinemanpage, Ich verstehe

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

daher möchte die Person, die das Skript geschrieben hat, aus irgendeinem Grund möglicherweise, dass die Ausgabe von an und nicht dialogan geht .stdoutstderr

Siehe auchReihenfolge der Weiterleitungen

Antwort3

Der Drehbuchautor definierte fd 3 wie folgt:

exec 3<> File.txt

Öffnen Sie "File.txt" und weisen Sie ihm fd 3 zu. Maximale Dateideskriptoren: 255

read -n 4 <&3

Nur 4 Zeichen lesen.

echo -n . >&3

Schreiben Sie dort einen Dezimalpunkt.

exec 3>&-

Schließen Sie fd 3.

cat File.txt

==> 1234,67890

Antwort4

Ich habe den Zweck des Dateideskriptors und des Befehls "3> & 1 1> & 2 2> & 3" anhand des folgenden Beispiels verstanden

#!/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"

Wenn Sie dieses Beispiel ausführen, sehen Sie, dass die Dateideskriptoren neu angeordnet und die Ausgabe geändert werden.

verwandte Informationen