Pokud jste obeznámeni se základními příkazy Linuxu, měli byste se také naučit koncept přesměrování vstupu a výstupu.
Už víte, jak funguje příkaz Linux. Bere vstup a dává vám výstup. Na scéně je zde několik hráčů. Řeknu vám o nich.
Stdin, stdout a stderr
Když spustíte příkaz Linuxu, jsou zde tři datové proudy, které v něm hrají roli:
- Standardní vstup (stdin) je zdrojem vstupních dat. Standardně je stdin jakýkoli text zadaný z klávesnice. ID streamu je 0.
- Standardní výstup (stdout) je výsledkem příkazu. Ve výchozím nastavení se zobrazuje na obrazovce. ID streamu je 1.
- Standardní chyba (stderr) je chybová zpráva (pokud existuje) vytvořená příkazy. Ve výchozím nastavení se na obrazovce zobrazuje také stderr. ID streamu je 2.
Tyto streamy obsahují data ve formě prostého textu v takzvané vyrovnávací paměti.

Představte si to jako proud vody. Potřebujete zdroj vody, například kohoutek. Napojíte na něj trubku a můžete ji buď uložit do kbelíku (spis), nebo zalévat rostliny (vytisknout). V případě potřeby jej můžete také připojit k jinému kohoutku. V podstatě přesměrováváte vodu.
Linux má také tento koncept přesměrování, kde můžete přesměrovat stdin, stdout a stderr z jejich obvyklého umístění na jiný soubor nebo příkaz (nebo dokonce periferní zařízení, jako jsou tiskárny).
Dovolte mi ukázat, jak přesměrování funguje a jak jej můžete použít.
Přesměrování výstupu

První a nejjednodušší formou přesměrování je přesměrování výstupu, také nazývané přesměrování stdout.
Již víte, že standardně se výstup příkazu zobrazuje na obrazovce. Například používám příkaz ls k výpisu všech souborů a toto je výstup, který dostanu:
[email protected]:~$ ls
appstxt new.txt static-ip.txt
Pomocí přesměrování výstupu můžete přesměrovat výstup do souboru. Pokud tyto výstupní soubory neexistují, shell jej vytvoří.
command > file
Dovolte mi například uložit výstup příkazu ls do souboru s názvem output.txt:
[email protected]:~$ ls > output.txt
Výstupní soubor je vytvořen předem
Jaký by podle vás měl být obsah tohoto výstupního souboru? Dovolte mi použít příkaz cat, abych vám ukázal překvapení:
[email protected]:~$ cat output.txt
appstxt
new.txt
output.txt
static-ip.txt
Všimli jste si, že tam byl zahrnut soubor output.txt ? Tento příklad jsem záměrně vybral, abych vám to ukázal.
Výstupní soubor, na který je stdout přesměrován, je vytvořen před spuštěním zamýšleného příkazu. Proč? Protože potřebuje mít připravený výstupní cíl, kam bude výstup odeslán.
Připojit místo clobber
Jedním z často ignorovaných problémů je, že pokud přesměrujete na soubor, který již existuje, shell soubor nejprve vymaže (vymaže). To znamená, že stávající obsah výstupního souboru bude odstraněn a nahrazen výstupem příkazu.
Místo přepisování jej můžete připojit pomocí>> syntaxe přesměrování.
command >> file
Tip :Clobbling v aktuální relaci shellu můžete zakázat pomocí:set -C
Proč byste přesměrovali stdout? Výstup můžete uložit pro budoucí použití a analyzovat jej později. To je zvláště užitečné, když je výstup příkazu příliš velký a zabírá celou obrazovku. Je to jako shromažďování protokolů.
Přesměrování potrubí

Než uvidíte přesměrování stdin, měli byste se dozvědět o přesměrování potrubí. Toto je běžnější a pravděpodobně to budete často používat.
Pomocí přesměrování potrubí odešlete standardní výstup příkazu na standardní vstup jiného příkazu.
command 1 | command 2
Dovolte mi ukázat vám praktický příklad. Řekněme, že chcete spočítat počet viditelných souborů v aktuálním adresáři. Můžete použít ls -1 (je to číslo jedna, ne písmeno L) pro zobrazení souborů v aktuálním adresáři:
[email protected]:~$ ls -1
appstxt
new.txt
output.txt
static-ip.txt
Pravděpodobně již víte, že příkaz wc se používá pro počítání počtu řádků v souboru. Pokud zkombinujete oba tyto příkazy s roura, získáte toto:
[email protected]:~$ ls -1 | wc -l
4
S roura sdílejí oba příkazy stejnou vyrovnávací paměť. Výstup prvního příkazu se uloží do vyrovnávací paměti a stejná vyrovnávací paměť se poté použije jako vstup pro další příkaz.
Uvidíte výsledek posledního příkazu v kanálu. To je zřejmé, protože stdout předchozího příkazu (příkazů) je předán dalším příkazům namísto přechodu na obrazovku.
Přesměrování potrubí nebo potrubí není omezeno na připojení pouze dvou příkazů. Můžete připojit více příkazů, pokud lze výstup jednoho příkazu použít jako vstup příkazu dalšího.
command_1 | command_2 | command_3 | command_4
Pamatujte si, že stdout/stdin je kus dat, nikoli názvy souborů
Někteří noví uživatelé Linuxu jsou při používání přesměrování zmateni. Pokud příkaz vrátí spoustu názvů souborů jako výstup, nemůžete tyto názvy souborů použít jako argument.
Pokud například použijete příkaz find k nalezení všech souborů končících příponou .txt, nemůžete jej předat kanálem a přesunout nalezené soubory do nového adresáře, ne přímo takto:
find . -type f -name "*.txt" | mv destination_directory
To je důvod, proč často uvidíte příkaz find použitý v konjugaci s příkazem exec nebo xargs. Tyto speciální příkazy ‚převedou text se spoustou názvů souborů na název souboru‘, který lze předat jako argument.
find . -type f -name "*.txt" | xargs -t -I{} mv {} ../new_dir
Přesměrování vstupu

Přesměrování stdin můžete použít k předání obsahu textového souboru příkazu, jako je tento:
command < file
Neuvidíte, že by se stdin hodně používal. Je to proto, že většina linuxových příkazů přijímá názvy souborů jako argument, a proto často není vyžadováno přesměrování stdin.
Vezměte si například toto:
head < filename.txt
Výše uvedený příkaz mohl být právě head filename.txt (bez <).
Není to tak, že by přesměrování stdin bylo úplně zbytečné. Některé příkazy na to spoléhají. Vezměte si například příkaz tr. Tento příkaz toho umí hodně, ale v příkladu níže převede vstupní text z malých na velká písmena:
tr a-z A-Z < filename.txt
Ve skutečnosti se použití stdin doporučuje speciálně přes potrubí, aby se zabránilo zbytečnému použití příkazu cat.
Mnoho lidí by například použilo výše uvedený příklad s cat a pak na něm použili tr. Upřímně řečeno, zde není potřeba používat kočku.
cat filename.txt | tr a-z A-Z
Kombinovat přesměrování
Můžete kombinovat stdin, stdout a přesměrování potrubí podle vašich potřeb.
Například níže uvedený příkaz vypíše všechny soubory .txt v aktuálním adresáři a poté provede počet těchto souborů .txt a uloží výstup do nového souboru.
ls *.txt | wc -l > count.txt
Chyba přesměrování
Někdy, když spustíte nějaký příkaz nebo skript, uvidíte, že se na obrazovce zobrazí chybová zpráva.
[email protected]:~$ ls -l ffffff > output.txt
ls: cannot access 'ffffff': No such file or directory
Na začátku tohoto článku jsem zmínil, že existují tři datové toky a stderr je jeden z výstupních datových toků, který se ve výchozím nastavení zobrazuje na obrazovce.
Můžete také přesměrovat stderr. Protože se jedná o výstupní datový tok, můžete použít stejný symbol> nebo>> přesměrování, který jste použili pro standardní přesměrování.
Ale jak rozlišíte mezi stdout a stderr, když jsou oba výstupní datový tok? Podle jejich ID streamu (také nazývaného deskriptor souboru).
Datový stream | ID streamu |
---|---|
stdin | 0 |
stdout | 1 |
stderr | 2 |
-t, | –seznam |
-u, | –aktualizace |
-x, | –extrahovat, –get |
-j, | –bzip2 |
-z, | –gzip, –gunzip, –ungzip |
Ve výchozím nastavení, když použijete symbol přesměrování výstupu>, ve skutečnosti to znamená 1>. Řečeno slovy, říkáte, že se zde odebírá datový tok s ID 1.
Když musíte přesměrovat stderr, použijete jeho ID jako 2> nebo 2>>. To znamená, že přesměrování výstupu je pro datový tok stderr (ID 2).
Příklady přesměrování Stderr
Dovolte mi, abych vám to ukázal na několika příkladech. Předpokládejme, že chcete pouze uložit chybu, můžete použít něco takového:
[email protected]:~$ ls fffff 2> error.txt
[email protected]:~$ cat error.txt
ls: cannot access 'fffff': No such file or directory
To bylo jednoduché. Udělejme to trochu složitější (a užitečnější):
[email protected]:~$ ls -l new.txt ffff > output.txt 2> error.txt
[email protected]:~$ cat output.txt
-rw-rw-r-- 1 abhishek abhishek 0 May 5 10:25 new.txt
[email protected]:~$ cat error.txt
ls: cannot access 'ffff': No such file or directory
Ve výše uvedeném příkladu se příkaz ls pokouší zobrazit dva soubory. U jednoho souboru je to úspěšné a u druhého chyba. Takže jsem zde přesměroval stdout na ouput.txt (s>) a stderr na error.txt (s 2>).
Můžete také přesměrovat stdout i stderr do stejného souboru. Existují způsoby, jak to udělat.
V níže uvedeném příkladu nejprve posílám stderr (s 2>>) do souboru combined.txt v režimu připojení. A pak je stdout (s>>) odeslán do stejného souboru v režimu připojení.
[email protected]:~$ ls -l new.txt fff 2>> combined.txt >> combined.txt
[email protected]:~$ cat combined.txt
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 abhishek abhishek 0 May 5 10:25 new.txt
Dalším způsobem, a to je preferovaný, je použít něco jako 2>&1. Což lze zhruba přeložit jako „přesměrování stderr na stejnou adresu jako stdout“.
Vezměme si předchozí příklad a tentokrát použijte 2>&1 k přesměrování stdout i stderr do stejného souboru.
[email protected]:~$ ls -l new.txt fff > output.txt 2>&1
[email protected]:~$ cat output.txt
ls: cannot access 'fff': No such file or directory
-rw-rw-r-- 1 abhishek abhishek 0 May 5 10:25 new.txt
Mějte na paměti, že nemůžete použít 2>>&1, abyste jej použili v režimu připojení. 2>&1 již přejde do režimu připojení.
Můžete také použít nejprve 2> a poté použít 1>&2 k přesměrování stdout do stejného souboru jako stderr. V podstatě je to „>&“, které přesměrovává jeden datový tok na jiný.
Přehled
- Existují tři datové toky. Jeden vstupní, stdin (0) a dva výstupní datové toky stdout (1) a stderr (2).
- Klávesnice je výchozí standardní zařízení a obrazovka je výchozí výstupní zařízení.
- Přesměrování výstupu se používá s> nebo>> (pro režim připojení).
- Přesměrování vstupu se používá s <.
- Stderr lze přesměrovat pomocí 2> nebo 2>>.
- Stderr a stdout lze kombinovat pomocí 2>&1.
Protože se učíte o přesměrování, měli byste také vědět o příkazu tee. Tento příkaz umožňuje současné zobrazení na standardní výstup a uložení do souboru.
Doufám, že se vám tento podrobný průvodce o přesměrování v Linuxu líbil. Pokud máte stále pochybnosti nebo máte návrhy na vylepšení tohoto článku, dejte mi prosím vědět v sekci komentářů.