GNU/Linux >> Znalost Linux >  >> Linux

Jak přesměrovat výstup příkazu shellu

Skripty shellu poskytují velmi výkonnou funkci:možnost přesměrovat výstup z příkazů a skriptů a odeslat jej do souborů, zařízení nebo dokonce jako vstup do jiných příkazů nebo skriptů.

Tento článek se zaměřuje na výstup příkazů a skriptů.

Typy výstupu

Příkazy a skripty v shellu mohou generovat dva základní typy výstupů:

  • STDOUT: Normální výstup z příkazu/skriptu (deskriptor souboru 1)
  • STDERR: Chybový výstup z příkazu/skriptu (deskriptor souboru 2)

Ve výchozím nastavení jsou STDOUT a STDERR odesílány na obrazovku vašeho terminálu.

Pokud jde o vstup, STDIN standardně čte vstup z klávesnice (deskriptor souboru 0). Deskriptor souboru je jedinečný identifikátor pro soubor nebo jiný I/O prostředek.

Jak přesměrovat výstup shellu

Existuje několik způsobů, jak přesměrovat výstup ze skriptů a příkazů prostředí.

1. Přesměrovat STDOUT

Pro následující příklady použiji tuto jednoduchou sadu souborů:

$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

Spouštím jednoduchý ls příkazy pro ilustraci STDOUT vs. STDERR, ale stejný princip platí pro většinu příkazů, které spouštíte ze shellu.

Standardní výstup mohu přesměrovat do souboru pomocí ls file* > my_stdout.txt :

$ls file* > my_stdout.txt

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

Dále spustím podobný příkaz, ale s 1 před > . Přesměrování pomocí > signál je stejný jako při použití 1> k tomu:Říkám shellu, aby přesměroval STDOUT na tento soubor. Pokud vynechám deskriptor souboru, standardně se používá STDOUT. Mohu to dokázat spuštěním sdiff příkaz pro zobrazení výstupu obou příkazů vedle sebe:

$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

Jak vidíte, oba výstupy mají stejný obsah.

2. Přesměrovat STDERR

Co je tedy na STDERR zvláštní? Pro demonstraci uvedu chybový stav do předchozího příkladu s ls file* non-existing-file* > my_normal_output.txt :

Zde je výsledek:

obraz

Zde jsou některé postřehy z výše uvedeného testu:

  1. Výstup o existujících souborech je správně odeslán do cílového souboru.
  2. Chyba (která se zobrazí, když se pokusím uvést něco, co neexistuje) se odešle na obrazovku. Toto je výchozí místo, kam se odesílají chyby, pokud je nepřesměrujete.

[ Stáhněte si cheat pro skriptování Bash Shell. ]

Dále přesměruji chybový výstup odkazem na deskriptor souboru 2 explicitně pomocí  ls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:

obraz

Ve výše uvedeném příkladu:

  1. Pole ls příkaz nezobrazí chybovou zprávu na obrazovce jako dříve.
  2. Normální výstup obsahuje to, co očekávám.
  3. Chybová zpráva je odeslána do souboru my_error_output.txt soubor.

3. Odešlete STDOUT a STDERR do stejného souboru

Další běžnou situací je odeslání STDOUT i STDERR na stejné soubor:

$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

V tomto příkladu je veškerý výstup (normální i chybový) odeslán do stejného souboru.

2>&1 konstrukce znamená „odešlete STDERR na stejné místo, kam posíláte STDOUT ."

4. Přesměrujte výstup, ale připojte soubor

Ve všech předchozích příkladech, kdykoli jsem přesměroval nějaký výstup, použil jsem jediný > , což znamená „odešlete něco do tohoto souboru a spusťte soubor od začátku ." V důsledku toho, pokud cílový soubor existuje, je přepsán.

Pokud chci připojit k existujícímu souboru, musím použít >> . Pokud soubor ještě neexistuje, bude vytvořen:

$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. Přesměrování na jiný proces nebo nikam

Výše uvedené příklady pokrývají přesměrování výstupu do souboru, ale můžete také přesměrovat výstupy na jiné procesy nebo dev/null .

Odesílání výstupu do jiných procesů je jednou z nejvýkonnějších funkcí shellu. Pro tento úkol použijte | (pipe) symbol, který posílá výstup jednoho příkazu na vstup dalšího příkazu:

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

Výše uvedený příklad uvádí moje procesy, filtruje všechny, které obsahují řetězec chrome , ignoruje řádek o mém grep a spočítá výsledné řádky. Pokud chci výstup odeslat do souboru, přidám > a název souboru na konec řetězce.

Nakonec zde je příklad, kdy chci ignorovat jeden z výstupů, 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

Protože tar příkaz nenalezl žádné soubory s názvy začínajícími na more-non-existing , na konci se zobrazí některé chybové zprávy.

Předpokládejme, že vytvářím nějaké skripty a nestarám se o to, abych tyto chyby viděl nebo je zachytil (vím, v reálném životě byste měli chybám předcházet a řešit je, ne je jen ignorovat):

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

/dev/null je speciální soubor zařízení, který je jako „černá díra“:Co tam pošlete, prostě zmizí.

[ Stáhněte si tohoto průvodce instalací aplikací v systému Linux. ]

6. Použijte přesměrování ve skriptu

obraz
=== 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

Tento velmi jednoduchý skript dělá následující:

  • Řádek 3:Provede příkaz v operačním systému a uloží se do proměnné DATE_TIME.
  • Řádek 6:Spustí ps příkaz a přesměruje na grep a do souboru.
    • Místo odesílání výstupu do souboru bych jej mohl poslat do proměnné (jako v řádku 3), ale v tomto případě chci spouštět jiné akce pomocí stejného výstupu, takže jej zachytím. V realističtější situaci může být mít soubor užitečný také při vývoji nebo odstraňování problémů, takže mohu snadněji prozkoumat, co příkaz generuje.
  • Řádek 8:Spouští další příkazy, přesměrovává výstupy na wc a výsledek přiřadí proměnné.
  • Řádek 9:Používá awk vybrat pouze sloupec 2 z výstupu a seřadit jej v sestupném pořadí (jen kvůli přidání dalšího kanálu).

Sbalit

To byly některé příklady přesměrování STDOUT a STDERR. Když to všechno dáte dohromady, uvědomíte si, jak mocné může být přesměrování. Zřetězením jednotlivých příkazů, manipulací s jejich výstupem a použitím výsledku jako vstupu pro další příkaz můžete provádět úkoly, které by jinak mohly vyžadovat vývoj skriptu nebo programu. Techniku ​​můžete také začlenit do jiných skriptů a použít vše jako stavební kameny.


Linux
  1. Jak přiřadit výstup příkazu proměnné shellu?

  2. Jak přesměrovat výstup programu do souboru ZIP?

  3. Jak přesměrovat výstup do souboru a stdout

  1. Jak připojit výstup do souboru?

  2. Jak přesměrovat výstup system() do souboru?

  3. Jak uložit výstup tohoto příkazu awk do souboru?

  1. Přesměrovat veškerý výstup do souboru pomocí Bash na Linuxu?

  2. Jak přesměrovat výstup služby systemd do souboru

  3. Jak přesměrovat výstup programu jako jeho vstup