Suche…


Syntax

  • Befehl </ Pfad / zu / Datei # Standardeingabe in Datei umleiten
  • Befehl> / Pfad / zu / Datei # Standardausgabe in flie umleiten
  • Befehl file_descriptor> / path / to / file # Ausgabe von file_descriptor in Datei umleiten
  • Befehl> & file_descriptor # Ausgabe an file_descriptor umleiten
  • Befehl file_descriptor> & another_file_descriptor # Umleitung file_descriptor auf another_file_descriptor
  • Befehl <& file_descriptor # Leiten Sie file_descriptor zur Standardeingabe um
  • Befehl &> / Pfad / zu / Datei # Standardausgabe und Standardfehler in Datei umleiten

Parameter

Parameter Einzelheiten
interne Dateideskriptor Eine ganze Zahl
Richtung Einer von > , < oder <>
Externer Dateideskriptor oder -pfad & gefolgt von einer Ganzzahl für den Dateideskriptor oder einem Pfad.

Bemerkungen

UNIX-Konsolenprogramme verfügen über eine Eingabedatei und zwei Ausgabedateien (Eingabe- und Ausgabeströme sowie Geräte werden vom Betriebssystem als Dateien behandelt.) Dies sind in der Regel die Tastatur bzw. der Bildschirm, aber alle können umgeleitet werden um von einer Datei oder einem anderen Programm zu kommen oder zu gehen.

STDIN ist eine Standardeingabe und empfängt die interaktiven Eingaben des Programms. STDIN wird normalerweise der Dateideskriptor 0 zugewiesen.

STDOUT ist Standardausgabe. Was auf STDOUT wird als "Ergebnis" des Programms betrachtet. STDOUT wird normalerweise der Dateideskriptor 1 zugewiesen.

STDERR Fehlermeldungen angezeigt. Wenn ein Programm von der Konsole aus ausgeführt wird, wird STDERR STDOUT auf dem Bildschirm ausgegeben und kann nicht von STDOUT . STDERR wird normalerweise der Dateideskriptor 2 zugewiesen.

Die Reihenfolge der Weiterleitung ist wichtig

command > file 2>&1

STDOUT beide ( STDOUT und STDERR ) zur Datei um.

command 2>&1 > file

Umleitungen nur STDOUT , weil der Dateideskriptor 2 in die Datei umgeleitet wird , auf den Dateideskriptor 1 (die nicht die Datei file noch , wenn die Anweisung ausgewertet wird).

Jeder Befehl in einer Pipeline hat ein eigenes STDERR (und STDOUT ), da es sich bei jedem STDOUT um einen neuen Prozess handelt. Dies kann zu überraschenden Ergebnissen führen, wenn Sie davon ausgehen, dass eine Umleitung die gesamte Pipeline beeinflusst. Zum Beispiel dieser Befehl (zur besseren Lesbarkeit umschlossen):

$ python -c 'import sys;print >> sys.stderr, "Python error!"' \
| cut -f1 2>> error.log

druckt "Python-Fehler!" zur Konsole und nicht zur Protokolldatei. Hängen Sie den Fehler stattdessen an den Befehl, den Sie erfassen möchten:

$ python -c 'import sys;print >> sys.stderr, "Python error!"' 2>> error.log \
| cut -f1 

Standardausgabe umleiten

> Umleitung der Standardausgabe (auch bekannt als STDOUT ) des aktuellen Befehls in eine Datei oder einen anderen Deskriptor.

Diese Beispiele schreiben die Ausgabe des ls in die Datei file.txt

ls >file.txt
> file.txt ls

Die Zieldatei wird erstellt, wenn sie nicht vorhanden ist. Andernfalls wird diese Datei abgeschnitten.

Der Standardumleitungsdeskriptor ist die Standardausgabe oder 1 wenn keine angegeben ist. Dieser Befehl entspricht den vorherigen Beispielen, wobei die Standardausgabe explizit angegeben ist:

ls 1>file.txt

Hinweis: Die Umleitung wird von der ausgeführten Shell und nicht vom ausgeführten Befehl initialisiert, daher erfolgt sie vor der Befehlsausführung.

STDIN umleiten

< liest aus seinem rechten Argument und schreibt zu seinem linken Argument.

Um eine Datei in STDIN zu schreiben, sollten Sie /tmp/a_file lesen und in STDIN schreiben, dh 0</tmp/a_file

Hinweis: Der interne Dateideskriptor ist standardmäßig auf 0 ( STDIN ) für <

$ echo "b" > /tmp/list.txt
$ echo "a" >> /tmp/list.txt
$ echo "c" >> /tmp/list.txt
$ sort < /tmp/list.txt
a
b
c

Umleiten von STDOUT und STDERR

Dateideskriptoren wie 0 und 1 sind Zeiger. Wir ändern, worauf Dateideskriptoren bei der Umleitung verweisen. >/dev/null bedeutet 1 zeigt auf /dev/null .

Zuerst zeigen wir 1 ( STDOUT ) auf /dev/null dann Punkt 2 ( STDERR ) auf das, worauf 1 verweist.

# STDERR is redirect to STDOUT: redirected to /dev/null,
# effectually redirecting both STDERR and STDOUT to /dev/null
echo 'hello' > /dev/null 2>&1
4,0

Dies kann weiter verkürzt werden:

echo 'hello' &> /dev/null

Dieses Formular kann jedoch in der Produktion unerwünscht sein, wenn die Kompatibilität mit der Shell problematisch ist, da es mit POSIX kollidiert, Mehrdeutigkeiten beim Analysieren einführt und Shells ohne diese Funktion dies falsch interpretieren:

# Actual code
echo 'hello' &> /dev/null
echo 'hello' &> /dev/null 'goodbye'

# Desired behavior
echo 'hello' > /dev/null 2>&1
echo 'hello' 'goodbye' > /dev/null 2>&1

# Actual behavior
echo 'hello' &
echo 'hello' & goodbye > /dev/null

HINWEIS: Es ist bekannt, dass &> in Bash und Zsh wie gewünscht funktioniert.

Umleitung von STDERR

2 ist STDERR .

$ echo_to_stderr 2>/dev/null # echos nothing

Definitionen:

echo_to_stderr ist ein Befehl, der "stderr" in STDERR schreibt

echo_to_stderr () {
    echo stderr >&2
}

$ echo_to_stderr
stderr

Append vs Truncate

Abschneiden >

  1. Erstellen Sie die angegebene Datei, falls diese nicht vorhanden ist.
  2. Abschneiden (Dateiinhalt entfernen)
  3. In die Datei schreiben
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines

$ cat /tmp/lines
second line

Anhängen >>

  1. Erstellen Sie die angegebene Datei, falls diese nicht vorhanden ist.
  2. Datei anhängen (Schreiben am Ende der Datei).
# Overwrite existing file
$ echo "first line" > /tmp/lines

# Append a second line
$ echo "second line" >> /tmp/lines

$ cat /tmp/lines
first line
second line

STDIN, STDOUT und STDERR erklärt

Befehle haben einen Eingang (STDIN) und zwei Arten von Ausgängen, Standardausgang (STDOUT) und Standardfehler (STDERR).

Zum Beispiel:

STDIN

root@server~# read
Type some text here

Die Standardeingabe dient zur Eingabe eines Programms. (Hier verwenden wir das read Builtin , um eine Zeile aus STDIN zu lesen.)

STDOUT

root@server~# ls file
file

Die Standardausgabe wird im Allgemeinen für die "normale" Ausgabe eines Befehls verwendet. Zum Beispiel ls listet die Dateien, so werden die Dateien an STDOUT gesendet.

STDERR

root@server~# ls anotherfile
ls: cannot access 'anotherfile': No such file or directory

Standardfehler werden (wie der Name schon sagt) für Fehlermeldungen verwendet. Da es sich bei dieser Nachricht nicht um eine Liste von Dateien handelt, wird sie an STDERR gesendet.

STDIN, STDOUT und STDERR sind die drei Standardströme. Sie sind in der Shell durch eine Nummer und nicht durch einen Namen gekennzeichnet:

0 = Standard in
1 = Standard aus
2 = Standardfehler

Standardmäßig ist STDIN an die Tastatur angeschlossen, und STDOUT und STDERR werden im Terminal angezeigt. Wir können jedoch entweder STDOUT oder STDERR an das weiterleiten, was wir brauchen. Nehmen wir zum Beispiel an, dass Sie nur den Standard out benötigen und alle Fehlermeldungen, die auf dem Standardfehler gedruckt werden, unterdrückt werden sollen. Dann verwenden wir die Deskriptoren 1 und 2 .

Umleitung von STDERR nach / dev / null
Nehmen wir das vorige Beispiel

root@server~# ls anotherfile 2>/dev/null
root@server~#

In diesem Fall wird ein STDERR an / dev / null weitergeleitet (eine spezielle Datei, die alle darin enthaltenen Einträge ignoriert), so dass keine Fehlerausgabe in der Shell erfolgt.

Umleiten mehrerer Befehle in dieselbe Datei

{
  echo "contents of home directory"
  ls ~
} > output.txt

Named Pipes verwenden

Manchmal möchten Sie möglicherweise etwas von einem Programm ausgeben und in ein anderes Programm eingeben, können jedoch keine Standardpipe verwenden.

ls -l | grep ".log"

Sie können einfach in eine temporäre Datei schreiben:

touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt

Für die meisten Anwendungen funktioniert das tempFile Niemand weiß jedoch, was tempFile tut, und jemand könnte es entfernen, wenn es die Ausgabe von ls -l in diesem Verzeichnis enthält. Hier kommt eine Named Pipe ins Spiel:

mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe

myPipe ist technisch gesehen eine Datei (alles ist in Linux), also ls -l in einem leeren Verzeichnis, in dem wir gerade eine Pipe erstellt haben:

mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l

Die Ausgabe ist:

prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe

Beachten Sie das erste Zeichen in den Berechtigungen. Es wird als Pipe und nicht als Datei aufgeführt.

Jetzt lass uns etwas Cooles machen.

Öffnen Sie ein Terminal und notieren Sie sich das Verzeichnis (oder erstellen Sie eines, damit die Bereinigung einfach ist), und erstellen Sie eine Pipe.

mkfifo myPipe

Jetzt lass uns etwas in die Pfeife legen.

echo "Hello from the other side" > myPipe

Sie werden feststellen, dass dies hängt, die andere Seite der Leitung ist immer noch geschlossen. Lassen Sie uns die andere Seite der Pfeife öffnen und das Zeug durchlassen.

Öffnen Sie ein anderes Terminal und wechseln Sie in das Verzeichnis, in dem sich die Pipe befindet (oder wenn Sie es wissen, stellen Sie es der Pipe voran):

cat < myPipe

Sie werden feststellen, dass nach hello from the other side Ausgabe hello from the other side das Programm im ersten Terminal beendet wird, wie auch im zweiten Terminal.

Führen Sie nun die Befehle in umgekehrter Reihenfolge aus. Beginnen Sie mit cat < myPipe und geben Sie etwas ein. Es funktioniert immer noch, weil ein Programm wartet, bis sich etwas in der Pipe befindet, bevor es beendet wird, weil es weiß, dass es etwas bekommen muss.

Named Pipes können nützlich sein, um Informationen zwischen Terminals oder zwischen Programmen zu verschieben.

Pfeifen sind klein. Sobald der Writer voll ist, blockiert der Writer, bis einige Leser den Inhalt lesen. Daher müssen Sie entweder den Reader und den Writer in verschiedenen Terminals oder das eine oder andere im Hintergrund ausführen:

 ls -l /tmp > myPipe &
 cat < myPipe

Weitere Beispiele mit Named Pipes:

  • Beispiel 1 - Alle Befehle auf demselben Terminal / derselben Shell

    $ { ls -l && cat file3; } >mypipe &
    $ cat <mypipe    
    # Output: Prints ls -l data and then prints file3 contents on screen
    
  • Beispiel 2 - Alle Befehle auf demselben Terminal / derselben Shell

    $ ls -l >mypipe &
    $ cat file3 >mypipe &
    $ cat <mypipe
    #Output: This prints on screen the contents of mypipe. 
    

    file3 dass zuerst der Inhalt von file3 angezeigt wird und dann die ls -l Daten angezeigt werden (LIFO-Konfiguration).

  • Beispiel 3 - Alle Befehle auf demselben Terminal / derselben Shell

    $ { pipedata=$(<mypipe) && echo "$pipedata"; } &
    $ ls >mypipe 
    # Output: Prints the output of ls directly on screen 
    

    $pipedata dass die Variable $pipedata nicht für die Verwendung in der Hauptterminal- / Main-Shell verfügbar ist, da die Verwendung von & eine Subshell verwendet und $pipedata nur in dieser Subshell verfügbar war.

  • Beispiel 4 - Alle Befehle auf demselben Terminal / derselben Shell

    $ export pipedata
    $ pipedata=$(<mypipe) &
    $ ls -l *.sh >mypipe
    $ echo "$pipedata"   
    #Output : Prints correctly the contents of mypipe
    

    Dadurch wird der Wert der $pipedata Variablen in der Haupt-Shell aufgrund der $pipedata Variablen korrekt $pipedata . Das Hauptterminal / die Haupt-Shell hängt nicht an dem Aufruf einer Hintergrund-Shell ( & ).

Fehlermeldungen an stderr ausgeben

Fehlermeldungen werden im Allgemeinen zu Debugging-Zwecken oder zur Bereitstellung einer umfassenden Benutzererfahrung in ein Skript aufgenommen. Schreiben Sie einfach eine Fehlermeldung wie diese:

cmd || echo 'cmd failed'

kann für einfache Fälle funktionieren, aber es ist nicht der übliche Weg. In diesem Beispiel verschmutzt die Fehlermeldung die tatsächliche Ausgabe des Skripts, indem sowohl Fehler als auch erfolgreiche Ausgabe in stdout gemischt werden.

Kurz gesagt, die Fehlermeldung sollte an stderr stdout . Es ist ziemlich einfach:

cmd || echo 'cmd failed' >/dev/stderr

Ein anderes Beispiel:

if cmd; then
    echo 'success'
else
    echo 'cmd failed' >/dev/stderr
fi

Im obigen Beispiel wird die Erfolgsmeldung auf stdout gedruckt, während die Fehlermeldung auf stderr gedruckt wird.

Eine bessere Möglichkeit, eine Fehlermeldung zu drucken, ist das Definieren einer Funktion:

err(){
    echo "E: $*" >>/dev/stderr
}

Wenn Sie jetzt einen Fehler drucken müssen:

err "My error message"

Umleitung zu Netzwerkadressen

2,04

Bash behandelt einige Pfade als besonders und kann einige Netzwerkkommunikationen durch Schreiben in /dev/{udp|tcp}/host/port . Bash kann keinen abhörenden Server einrichten, kann jedoch eine Verbindung initiieren, und für TCP können die Ergebnisse mindestens gelesen werden.

Um beispielsweise eine einfache Webanfrage zu senden, können Sie Folgendes tun:

exec 3</dev/tcp/www.google.com/80
printf 'GET / HTTP/1.0\r\n\r\n' >&3
cat <&3

Die Ergebnisse der Standardwebseite von www.google.com werden in stdout gedruckt.

Ähnlich

printf 'HI\n' >/dev/udp/192.168.1.1/6666

würde eine UDP-Nachricht mit HI\n an einen Listener unter 192.168.1.1:6666 senden



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow