web-dev-qa-db-de.com

sH-Befehl: Exec 2> & 1

Was macht dieser Befehl? 

exec 2>&1 
40
valodzka

Technisch gesehen kopiert oder kopiert er stderr auf stdout.

Normalerweise brauchen Sie den Exec nicht, um dies durchzuführen. Eine typischere Verwendung von exec bei Dateideskriptoren besteht darin, anzugeben, dass Sie eine Datei einem nicht verwendeten Dateideskriptor zuordnen möchten, z.

ls > mydirlist 2>&1

funktioniert, weil es sowohl stdout als auch stderr auf die Datei mydirlist verweist, während der Befehl

ls 2>&1 > mydirlist

weist nur stdout und nicht stderr an, mydirlist zu archivieren, da stderr eine Kopie von stdout gemacht wurde, bevor stdout zu mydirlist umgeleitet wurde.

Edit: So scannt die Shell von links nach rechts. Lesen Sie also die zweite als "copy stderr auf stdout", bevor sie "send stdout an mydirlist" aussagt. Lesen Sie dann den ersten Satz mit der Überschrift "Sende stdout an die Datei mydirlist", bevor er sagt "Duplizieren Sie stderr auf den von mir eingerichteten stdout". Ich kenne. Es ist absolut nicht intuitiv!

33
Rob Wells

Einer der besseren Artikel, die ich auf "2> & 1" gesehen habe, ist Bash One-Liner erklärt, Teil III: Alles über Weiterleitungen .

Was die aktuellen Antworten auf diese Frage jedoch nicht liefern, ist, warum Sie dies nach einem einfachen "exec" tun möchten. Wie die bash-Manpage für den exec-Befehl erläutert: "Wenn der Befehl nicht angegeben ist, werden Umleitungen in der aktuellen Shell wirksam.".

Ich habe ein einfaches Skript namens out-and-err.py geschrieben, das eine Ausgabezeile in stdout und eine weitere Zeile in stderr schreibt:

#!/usr/bin/python
import sys
sys.stdout.write('this is stdout.\n')
sys.stderr.write('this is stderr.\n')

Und dann habe ich das in ein Shell-Skript namens out-and-err.sh mit "exec 2> & 1" verpackt:

#!/bin/bash
exec 2>&1
./out-and-err.py

Wenn ich nur das Python-Skript ausführe, sind stdout und stderr getrennt:

$ ./out-and-err.py 1> out 2> err
$ cat out
this is stdout.
$ cat err
the is stderr.

Wenn ich jedoch das Shell-Skript starte, können Sie sehen, dass der Exec für alles nach stderr sorgt:

$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$

Wenn Ihr Shell-Wrapping-Skript mehr als nur einen einzigen Python-Befehl ausführt und Sie die gesamte Ausgabe in stdout kombinieren müssen, wird Ihnen das Ausführen von "exec 2> & 1" leicht fallen.

29
Brian Taylor

Es verbindet Standardfehler mit Standardausgang

der 2 ist stderr und 1 ist stdout. Wenn Sie ein Programm ausführen, erhalten Sie die normale Ausgabe in stdout, aber Fehler oder Warnungen gehen normalerweise an stderr. Wenn Sie beispielsweise die gesamte Ausgabe an eine Datei übergeben möchten, ist es nützlich, stderr zuerst mit stdout mit 2>&1 zu kombinieren.

12
Charles Ma

Wie @cma sagte, wird stderr auf stdout gesetzt. Möglicherweise möchten Sie dieses Verhalten, indem Sie grep oder ein anderes Dienstprogramm verwenden, um Ausgaben zu erfassen, die nur in stderr angezeigt werden. Oder Sie möchten vielleicht nur die gesamte Ausgabe, einschließlich stderr, für eine spätere Verarbeitung in einer Datei speichern.

2
Mark Rushakoff

An diesem Tag war ich auch an diesem Problem scheiße, aber jetzt springe ich aus ihm heraus ... Bitte erlauben Sie mir zu erklären, was passiert, nachdem Sie exec 1>&2 in CLI eingegeben haben.

Ich möchte das Problem Stück für Stück zerstören. Wenn Sie also das Wissen bereits kennen, überfliegen Sie es einfach, um Zeit zu sparen.

  • Was ist exec steht für:

exec ist ein in Linux integrierter Befehl. Anders als der traditionelle Befehl, der nur einen Unter-Shell-Prozess umfasst, könnte exec den aktuellen Shell-Prozess ändern.

  • Was ist eine E/A-Umleitung: Umleitung ist eine Funktion in Linux. Hiermit können Sie die Standard-Ein-/Ausgabegeräte ändern. In Linux gibt es standardmäßig drei Dateideskriptoren . Handle Name Description 0 stdin Standard input 1 stdout Standard output 2 stderr Standard error

  • Lass mich ein Beispiel sehen:

    1. ein neues Terminal öffnen
    2. Rufen Sie die Prozess-ID des termianl-Prozesses ab $ pstree -p | grep 'term' | tr -d ' '
    3. Überprüfen Sie den Prozessdateideskriptor .$ Sudo ls -l /proc/{pid}/fdbash $ pstree -p | grep -i 'terminal' | tr -d ' ' ||||-gnome-terminal-(6008)-+-bash(7641)-+-grep(8355) $ Sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Wie Sie sehen, listet die Variable ls die PID-Prozessdatei (6860) auf. Zuerst benennen sie alle nach der Nummer (0, 1, 2), zweitens verknüpfen sie alle mit/dev/pts/3, was bedeutet, dass alle Standardeingaben/-ausgänge/-fehler in pts3 angezeigt werden.
    4. Ändern Sie die Standardausgabe in /tmp/stdoutbash $ ls /tmp/stdout ls: cannot access '/tmp/stdout': No such file or directory $ exec 1>/tmp/stdout $ ls $ pwd $ echo "Are you ok" $ Die Befehlsausgabe war zu diesem Zeitpunkt verschwunden.
    5. Öffnen Sie ein neues Terminal, um die proc-Datei zu überprüfen bash $ Sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /tmp/stdout lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Offensichtlich können wir feststellen, dass die 1 (Dateideskriptor) bereits den Link zu/tmp/stdout ändert. Bei uns wird die Standardausgabe nach/tmp/stdout übertragen
    6. Stellen Sie die Umleitung .bash $ exec 1>&2 $ cat /tmp/stdout a.sh /home/alopex Are you ok $ Sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 .__ wieder her. Wiederum die Verknüpfung 1 (Dateideskriptor) zu/dev/pts/3, können Sie die Ausgabe erneut sehen.
  • Zusammenfassung:

  • exec 1>&2 macht die Standardausgabe ---> Standardfehler
0
Alopex

Eine recht nützliche Anwendung von exec 2>&1, die ich gefunden habe, ist, wenn Sie stderr und stdout für mehrere durch Semikola getrennte Befehle zusammenführen möchten. Mein spezielles Beispiel geschah, als ich in PHP mehr als einen Befehl an popen sendete und wollte, dass die Fehler verschachtelt angezeigt wurden, als würden Sie die Befehle an einem Shell-Prompt eingeben:

$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$ 

Folgendes fasst nicht stderr und stdout zusammen, außer der letzten echo (was sinnlos ist, da die yikes den Fehler verursacht):

echo hi ; yikes ; echo there 2>&1

Ich kann die zusammengeführte Ausgabe auf "harte Weise" wie folgt erhalten:

echo hi 2>&1; yikes 2>&1; echo there 2>&1

Es sieht viel sauberer und weniger fehleranfällig aus, wenn Sie exec verwenden:

exec 2>&1 ; echo hi; echo yikes; echo there

Sie erhalten die Ausgabe von stdout und stderr genau so, wie Sie es auf dem Terminal sehen würden, wenn Sie die drei durch ein Semikolon getrennten Befehle ausführen.

0
drchuck