GNU/Linux >> LINUX-Kenntnisse >  >> Linux

So leiten Sie die Shell-Befehlsausgabe um

Shell-Skripte bieten eine sehr mächtige Funktion:die Fähigkeit, die Ausgabe von Befehlen und Skripten umzuleiten und sie an Dateien, Geräte oder sogar als Eingabe für andere Befehle oder Skripte zu senden.

Dieser Artikel konzentriert sich auf die Befehls- und Skriptausgabe.

Arten der Ausgabe

Befehle und Skripte in einer Shell können zwei grundlegende Arten von Ausgaben erzeugen:

  • STDOUT: Die normale Ausgabe eines Befehls/Skripts (Dateideskriptor 1)
  • STDERR: Die Fehlerausgabe eines Befehls/Skripts (Dateideskriptor 2)

Standardmäßig werden STDOUT und STDERR an den Bildschirm Ihres Terminals gesendet.

In Bezug auf die Eingabe STDIN liest standardmäßig Eingaben von der Tastatur (Dateideskriptor 0). Ein Dateideskriptor ist ein eindeutiger Bezeichner für eine Datei oder eine andere I/O-Ressource.

Wie man die Shell-Ausgabe umleitet

Es gibt mehrere Möglichkeiten, die Ausgabe von Shell-Skripten und -Befehlen umzuleiten.

1. STDOUT umleiten

Für die folgenden Beispiele verwende ich diesen einfachen Satz von Dateien:

$ls -la file*
-rw-r--r--. 1 admin2 admin2  7 Mar 27 15:34 file1.txt
-rw-r--r--. 1 admin2 admin2 10 Mar 27 15:34 file2.txt
-rw-r--r--. 1 admin2 admin2 13 Mar 27 15:34 file3.txt

Ich verwende ein einfaches ls Befehle, um STDOUT vs. STDERR zu veranschaulichen, aber das gleiche Prinzip gilt für die meisten Befehle, die Sie von einer Shell aus ausführen.

Ich kann die Standardausgabe mit ls file* > my_stdout.txt in eine Datei umleiten :

$ls file* > my_stdout.txt

$ cat my_stdout.txt 
file1.txt
file2.txt
file3.txt

Als nächstes führe ich einen ähnlichen Befehl aus, aber mit einem 1 vor > . Umleitung mit > Signal ist dasselbe wie die Verwendung von 1> Um dies zu tun:Ich sage der Shell, dass sie die STDOUT in diese Datei umleiten soll. Wenn ich den Dateideskriptor weglasse, wird standardmäßig STDOUT verwendet. Ich kann dies beweisen, indem ich sdiff ausführe Befehl, um die Ausgabe beider Befehle nebeneinander anzuzeigen:

$ls file* 1> my_other_stdout.txt

$sdiff my_stdout.txt my_other_stdout.txt
file1.txt			             file1.txt
file2.txt			             file2.txt
file3.txt			             file3.txt

Wie Sie sehen, haben beide Ausgaben denselben Inhalt.

2. STDERR umleiten

Was ist nun das Besondere an STDERR? Zur Veranschaulichung füge ich dem vorherigen Beispiel mit ls file* non-existing-file* > my_normal_output.txt eine Fehlerbedingung hinzu :

Hier ist das Ergebnis:

Bild

Hier sind einige Beobachtungen aus dem obigen Test:

  1. Die Ausgabe über die vorhandenen Dateien wird korrekt an die Zieldatei gesendet.
  2. Der Fehler (der angezeigt wird, wenn ich versuche, etwas aufzulisten, das nicht existiert) wird an den Bildschirm gesendet. Dies ist der Standardort, an den Fehler gesendet werden, es sei denn, Sie leiten sie um.

[ Laden Sie einen Bash Shell Scripting Cheat Sheet herunter. ]

Als Nächstes leite ich die Fehlerausgabe um, indem ich explizit auf Dateideskriptor 2 verweise mit  ls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:

Bild

Im obigen Beispiel:

  1. Die ls Befehl zeigt die Fehlermeldung nicht wie zuvor auf dem Bildschirm an.
  2. Die normale Ausgabe enthält, was ich erwarte.
  3. Die Fehlermeldung wird an die my_error_output.txt gesendet Datei.

3. Senden Sie STDOUT und STDERR an dieselbe Datei

Eine andere übliche Situation besteht darin, sowohl STDOUT als auch STDERR an dasselbe zu senden Datei:

$ls file* non-existing-file* > my_consolidated_output.txt 2>&1

$ cat my_consolidated_output.txt 
ls: cannot access 'non-existing-file*': No such file or directory
file1.txt
file2.txt
file3.txt

In diesem Beispiel werden alle Ausgaben (normal und Fehler) an dieselbe Datei gesendet.

Der 2>&1 Konstruktion bedeutet "sende das STDERR an die gleiche Stelle, an die du das STDOUT sendest ."

4. Ausgabe umleiten, aber Datei anhängen

In allen vorherigen Beispielen habe ich immer, wenn ich eine Ausgabe umgeleitet habe, einen einzelnen > verwendet , was bedeutet "etwas an diese Datei senden und die Datei von Grund auf neu starten ." Als Ergebnis wird die Zieldatei, falls vorhanden, überschrieben.

Wenn ich anhängen möchte zu einer vorhandenen Datei muss ich >> verwenden . Wenn die Datei noch nicht existiert, wird sie erstellt:

$echo "Adding stuff to the end of a file" >> my_output.txt

$cat my_output.txt 
file1.txt
file2.txt
file3.txt
Adding stuff to the end of a file

5. Umleitung zu einem anderen Prozess oder ins Nirgendwo

Die obigen Beispiele behandeln die Umleitung der Ausgabe in eine Datei, aber Sie können Ausgaben auch an andere Prozesse oder dev/null umleiten .

Das Senden von Ausgaben an andere Prozesse ist eine der leistungsstärksten Funktionen einer Shell. Verwenden Sie für diese Aufgabe den | (Pipe)-Symbol, das die Ausgabe eines Befehls an die Eingabe des nächsten Befehls sendet:

ps -ef | grep chrome | grep -v grep | wc -l
21

Das obige Beispiel listet meine Prozesse auf und filtert alle, die die Zeichenfolge chrome enthalten , ignoriert die Zeile über mein grep Befehl und zählt die resultierenden Zeilen. Wenn ich die Ausgabe an eine Datei senden möchte, füge ich > hinzu und einen Dateinamen am Ende der Kette.

Schließlich ist hier ein Beispiel, in dem ich eine der Ausgaben ignorieren möchte, die STDERR:

$tar cvf my_files.tar file* more-non-existing*
file1.txt
file2.txt
file3.txt
tar: more-non-existing*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

Denn der tar Der Befehl hat keine Dateien gefunden, deren Namen mit more-non-existing beginnen , einige Fehlermeldungen werden am Ende angezeigt.

Angenommen, ich erstelle einige Skripte und kümmere mich nicht darum, diese Fehler zu sehen oder zu erfassen (ich weiß, dass Sie im wirklichen Leben die Fehler verhindern und behandeln sollten, anstatt sie einfach zu ignorieren):

$tar cvf my_files.tar file* more-non-existing* 2> /dev/null
file1.txt
file2.txt
file3.txt

Der /dev/null ist eine spezielle Gerätedatei, die wie ein "schwarzes Loch" ist:Was Sie dorthin senden, verschwindet einfach.

[ Laden Sie diese Anleitung zur Installation von Anwendungen unter Linux herunter. ]

6. Verwenden Sie die Weiterleitung in einem Skript

Bild
=== SUMMARY OF INVESTIGATION OF chrome ===
Date/Time of the execution: 2022-03-25 18:05:50
Number of processes found.: 5
PIDs:
1245475
1249558
1316941
1382460
1384452

Dieses sehr einfache Skript macht Folgendes:

  • Zeile 3:Führt einen Befehl im Betriebssystem aus und speichert in der Variablen DATE_TIME.
  • Zeile 6:Führt ps aus Befehl und leitet zu grep weiter und in eine Datei.
    • Anstatt die Ausgabe an eine Datei zu senden, könnte ich sie an eine Variable senden (wie in Zeile 3), aber in diesem Fall möchte ich andere Aktionen mit derselben Ausgabe ausführen, also erfasse ich sie. In einer realistischeren Situation könnte es auch während der Entwicklung oder Fehlerbehebung hilfreich sein, die Datei zu haben, damit ich leichter untersuchen kann, was der Befehl generiert.
  • Zeile 8:Führt zusätzliche Befehle aus, leitet die Ausgaben nach wc um , und weist das Ergebnis einer Variablen zu.
  • Zeile 9:Benutzt awk um nur Spalte 2 aus der Ausgabe auszuwählen und sie in absteigender Reihenfolge zu sortieren (nur um eine weitere Pipe hinzuzufügen).

Abschluss

Dies waren einige Beispiele für die Umleitung von STDOUT und STDERR. Wenn Sie all dies zusammenfassen, erkennen Sie, wie mächtig Umleitung sein kann. Indem Sie einzelne Befehle verketten, ihre Ausgabe manipulieren und das Ergebnis als Eingabe für den nächsten Befehl verwenden, können Sie Aufgaben ausführen, für die Sie andernfalls ein Skript oder Programm entwickeln müssten. Sie könnten die Technik auch in andere Skripte integrieren und alles als Bausteine ​​verwenden.


Linux
  1. Wie leite ich die Ausgabe eines Programms in eine Zip-Datei um?

  2. So leiten Sie die Ausgabe eines bereits laufenden Prozesses um

  3. Wie leitet man die Ausgabe von system() in eine Datei um?

  4. Wie kann die Ausgabe des Zeitbefehls in eine Datei unter Linux umgeleitet werden?

  5. Befehlsausgabeumleitung auf Datei und Terminal

So speichern Sie die Befehlsausgabe in einer Datei unter Linux

So speichern Sie die Linux-Befehlsausgabe in einem Bild oder einer Textdatei

So leiten Sie die Ausgabe in eine Datei und stdout um

Wie hängt man die Ausgabe an eine Datei an?

Wie speichere ich die Ausgabe dieses awk-Befehls in einer Datei?

Wie drucke ich die Linux-Befehlsausgabe in eine Datei?