Was ist der Unterschied zwischen &> und 2> & 1

30

Es gibt zwei Arten, die Standardausgabe und den Standardfehler in die Standardausgabe umzuleiten . Aber welches ist besser? und warum &>gilt das als perfekt?

Ich kann nicht finden, was die Unterschiede sind, so dass viele Tutorials und sogar Bash-Handbücher &>besser sind!

Also warum soll ich verwenden &>und nicht2>&1

Hauptsächlich mit bashShell


EDIT: Danke für die Kommentare

Nur> & funktioniert in csh oder tcsh

In ksh funktioniert nur 2> & 1.

Nur Bindestrich verwenden> Datei 2> & 1 Umleitung

Dann welches, um sicherzustellen, dass mein Skript mit anderen Systemen kompatibel ist, unabhängig von den verwendeten Shells!

Maythux
quelle
Das Bessere ist, was Sie tun müssen. diese machen sehr unterschiedliche Dinge. Welche Shell benutzt du?
Skaperen
@ Kaperen mit bash
Maythux
1
was willst du erreichen
Skaperen
Ich möchte nur wissen, was die Unterschiede sind. Was ich will, ist nicht beides, aber ich muss nur wissen, ob das ein Unterschied ist, so dass einmal vor anderen
bevorzugt wird
2
&> somewhereist nur die Abkürzung für bash > somewhere 2>&1: In den Worten des bash-Handbuchs sind sie "symantisch äquivalent"
steeldriver

Antworten:

23

In der Manpage von Bash wird erwähnt, dass es zwei Möglichkeiten gibt, stderr und stdout umzuleiten : &> file und >& file. Beachten Sie, dass hier sowohl stderr als auch stdout steht.

In diesem Fall >file 2>&1leiten wir stdout (1) in file um, teilen aber auch stderr (2) mit, dass es an dieselbe Stelle wie stdout umgeleitet werden soll! Der Zweck mag also derselbe sein, aber die Idee ist etwas anders. Mit anderen Worten: "John, geh zur Schule; Suzzie geh dahin, wohin John geht".

Was ist mit Präferenz? &>ist eine bashSache. Wenn Sie also ein Skript portieren, ist dies nicht der Fall. Aber wenn Sie zu 100% sicher sind, dass Ihr Skript nur mit bash auf dem System funktioniert, ist das egal

Hier ist ein Beispiel mit dashder Debian-Amquist-Shell, die Ubuntus Standard ist.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Wie Sie sehen, wird stderr nicht umgeleitet

Um Ihre Änderungen in der Frage zu berücksichtigen, können Sie mit der if-Anweisung die Variable $ SHELL überprüfen und die Weiterleitungen entsprechend ändern

Sollte aber in den meisten Fällen > file 2>&1funktionieren


In technischer Hinsicht ist die Form [integer]>&wordgenannt wird Duplicating Output File Descriptor und ist eine Funktion von POSIX Shell Command Language - Standard spezifiziert, die von den meisten POSIX-konform und Brourne artigen Schalen unterstützt wird.

Siehe auch Was bedeutet & genau in der Ausgabeumleitung?

Sergiy Kolodyazhnyy
quelle
Was passiert dann, wenn andere Shells verwendet werden?
Maythux
zsh unterstützt &>.... @Maythux In Shells, die nicht unterstützen , müssen Sie &>z. B. dashdie >file 2>&1
einfache
Dann Welches, wenn ich sicher sein will, dass mein Skript mit verschiedenen Shells kompatibel ist
Maythux
3
@ Maythux verwenden >file 2>&1. Diese Arbeit an allen Muscheln
Sergiy Kolodyazhnyy
1
@ TSJNachos117 /etc/passwdFür jeden Benutzer festgelegte Shells sind interaktive Shells. Systemskripte sind in der Regel fürdash sofern nicht anders angegeben. Was die Standardeinstellung betrifft, hängt es davon ab, was /bin/shin Ubuntus Fall damit zusammenhängt dash. In RHEL ist es bash, in FreeBSD ist es tcsh Quelle und eine andere Quelle
Sergiy Kolodyazhnyy
6

Ich würde generell empfehlen, die Vorgehensweise von Bourne-again SHell zu befolgen , da bash die wohl beliebteste Unix-Shell überhaupt ist. Bash verwendet normalerweise entweder &>oder 2>&1. IMHO, keiner ist "perfekt", also empfehle ich, diesen Unsinn zu vergessen. Welches Sie verwenden sollten, hängt realistisch davon ab, was Sie zu tun versuchen.

2>&1Führt stderr mit stdout zusammen. Dies kann nützlich sein, wenn Sie beispielsweise stderr-Text weiterleiten möchten. Wenn Sie zum Beispiel sehen möchten, ob ein Programm eine bestimmte stderr-Nachricht druckt, aber nicht möchten, dass Ihr Bildschirm mit (vermutlich) unwichtigem Müll gefüllt ist, können Sie so etwas tun program 2>&1 | grep crashed, dass stdout und stderr von einem Programm aus durchsucht genannt "Programm" für das Wort "abgestürzt".

Wenn Sie jedoch nicht möchten, dass ein Programm überhaupt etwas druckt, können Sie einfach program &> /dev/nulleine spezielle Datei ausführen , die stderr und stdout nach / dev / null umleitet und die Dinge auf magische Weise verschwinden lässt. Wenn Sie die Ausgabe eines Programms speichern möchten (um möglicherweise einen Fehler oder etwas zu melden), können Sie sowohl stderr als auch stdout in eine Datei program &> log.txtumleiten: Alle Daten werden in eine Datei namens "log.txt" umgeleitet. Wenn Sie möchten , können Sie stdout und stderr über program 2> log.txt > log.txtoder umleiten. program 2>&1 | cat > log.txtBeide haben den gleichen Effekt wie using &>. Wenn Sie so etwas tun program 2>&1 > file, wird nur stdout umgeleitet, stderr kann jedoch weiterhin an ein anderes Programm wie cat weitergeleitet werden, das wie oben gezeigt umgeleitet werden kann. Tippen Sie jedoch&>ist einfacher als jedes der obigen Beispiele, da weniger Zeichen eingegeben werden müssen (und es für Menschen ein bisschen einfacher zu lesen ist). Beachten Sie, dass program 2> log.txt > log.txtdies mit größerer Wahrscheinlichkeit bei Nicht-Bash-Shells der Fall sein kann.

PS: Wenn Sie sich Sorgen machen, dass andere Benutzer andere Shells verwenden, können Sie eine erste Zeile Ihres Skripts hinzufügen, die als "magische Zahl" oder "Schebang" bezeichnet wird. Dies ist im Wesentlichen eine Möglichkeit, um sicherzustellen, dass andere Computer (insbesondere solche mit Unix-ähnlichen Betriebssystemen) wissen, mit welchem ​​Programm ein Skript ausgeführt werden soll. Unterschiedliche Skripte verwenden unterschiedliche Shebangs. Ein Shebang für ein Bash-Skript sieht folgendermaßen aus:

#!/bin/bash

Wenn Sie das Obige als erste Zeile eines bestimmten Skripts verwenden, wird bash im Allgemeinen zum Ausführen des Skripts verwendet. Dadurch wird es für jemanden viel schwieriger, das Skript versehentlich mit der falschen Shell auszuführen.

PS: Ich werde nicht lügen: Bis jetzt wusste ich nicht, dass man es gebrauchen kann >&, aber was Bash angeht, scheint es dasselbe zu tun wie &>. Sie lernen jeden Tag etwas Neues.

TSJNachos117
quelle
Ich bin zwar mit Ihnen einverstanden, dass die #!Leitung ausdrücklich angefordert wird bash, sie ist jedoch auf anderen Systemen nicht immer verfügbar. Sehr oft müssen Entwickler / Systemadministratoren portable Skripte für Systeme schreiben, auf denen sie bashmöglicherweise nicht verfügbar sind und deren Installation nicht unter ihrer Kontrolle steht bash. Das >file 2>&1ist halt viel tragbarer.
Sergiy Kolodyazhnyy
Sie haben oben einen Stornofehler gemacht, der nicht zu dem von Ihnen gewünschten Ergebnis führt. Stdout auf stdout umleiten, dann stdout umleiten und stderr auf dem ursprünglichen stdout belassen.
Ubfan1
Serg: Ich wollte nicht implizieren, dass Bash universell ist. Ich denke jedoch, dass mehr Leute es benutzen, als sagen (t) csh. Wenn Sie nicht wissen, was jemand anderes verwendet, und eine blinde Vermutung anstellen müssen, ist Bash wahrscheinlich die beste Wahl. Außerdem kenne ich mich mit Portabilität im Allgemeinen nicht aus, da ich nur bash verwende. Die Tatsache, dass >file 2>&1portabler ist, ist gut zu wissen. Ich werde eine Bearbeitung vornehmen, um das zu reflektieren.
TSJNachos117
Ubfan1, danke für die Info. Ich hätte in einer Million Jahren nie gedacht, dass Bash in diesem Fall stderr nicht in eine Datei umleiten würde. Ich habe gerade meine Antwort bearbeitet, um zu verhindern, dass andere den gleichen Fehler machen.
TSJNachos117
4

Aus dem Bash-Referenzhandbuch -> 3.6.4 Umleiten der Standardausgabe und des Standardfehlers :

Mit diesem Konstrukt können sowohl die Standardausgabe (Dateideskriptor 1) als auch die Standardfehlerausgabe (Dateideskriptor 2) in die Datei umgeleitet werden, deren Name die Erweiterung des Wortes ist.

Es gibt zwei Formate zum Umleiten von Standardausgaben und Standardfehlern:

&>word

und

>&word

Von den beiden Formen ist die erste bevorzugt. Dies ist semantisch äquivalent zu

>word 2>&1

Bei Verwendung der zweiten Form darf das Wort nicht zu einer Zahl oder einem '-' erweitert werden. In diesem Fall gelten aus Kompatibilitätsgründen andere Umleitungsoperatoren (siehe Duplizieren von Dateideskriptoren weiter unten).

Ebenfalls gut zu Gregs Wiki zu Input und Output -> 4.2. Manipulation des Dateideskriptors :

Der Einfachheit halber stellt Bash Ihnen auch eine weitere Form der Umleitung zur Verfügung. Der &> Umleitungsoperator ist eigentlich nur eine kürzere Version dessen, was wir hier gemacht haben [ 2>&1]; stdout und stderr in eine Datei umleiten.

fedorqui
quelle
4

Warum soll ich also &> und nicht 2> & 1 verwenden?

2>&1 ist die Standard-Bourne / POSIX-Shell.

&>ist eine Bash-Erweiterung und nicht de jure Standard.

Wenn Sie Skripte mit Bash-Erweiterungen schreiben, treten früher oder später bei Fehlern in der kryptischen Syntax Kratzer auf, weil sie in einer Standard-Shell ausgeführt werden.

Stephen M. Webb
quelle