Co jsou stdin, stdout a stderr v systému Linux?

stdin, stdouta stderrjsou tři datové toky vytvořené při spuštění příkazu Linux. Můžete je použít ke zjištění, zda jsou vaše skripty směrovány nebo přesměrovány. Ukážeme vám jak.

Proudy spojují dva body

Jakmile začnete se dozvědět o Linux a Unix-like operačních systémech, budete narazit na podmínkách stdin, stdouta stederr. Jedná se o tři standardní streamy, které jsou vytvořeny při spuštění příkazu Linux. Ve výpočetní technice je proud něco, co může přenášet data. V případě těchto streamů jsou tato data textová.

Datové toky, stejně jako vodní toky, mají dva konce. Mají zdroj a odliv. Bez ohledu na to, jaký příkaz Linux používáte, poskytuje jeden konec každého streamu. Druhý konec určuje shell, který spustil příkaz. Tento konec bude připojen k terminálovému oknu, připojen k potrubí nebo přesměrován na soubor nebo jiný příkaz podle příkazového řádku, který spustil příkaz.

Standardní proudy Linuxu

V Linuxu  stdinje standardní vstupní proud. Toto přijímá text jako vstup. Textový výstup z příkazu do shellu je dodáván prostřednictvím stdout(standardního out) streamu. Chybové zprávy z příkazu jsou odesílány prostřednictvím stderrproudu (standardní chyba).

Takže vidíte, že existují dva výstupní proudy, stdouta stderr, a jeden vstupní proud, stdin. Protože chybové zprávy a normální výstup mají každý svůj vlastní kanál pro jejich přenos do okna terminálu, lze s nimi manipulovat nezávisle na sobě.

S toky se zachází jako se soubory

S proudy v Linuxu - stejně jako téměř se vším ostatním - se zachází, jako by to byly soubory. Můžete číst text ze souboru a můžete do něj psát text. Obě tyto akce zahrnují proud dat. Koncept zpracování proudu dat jako souboru tedy není tak náročný.

Každému souboru přidruženému k procesu je přiděleno jedinečné číslo k jeho identifikaci. Toto se nazývá deskriptor souboru. Kdykoli je na souboru třeba provést akci, použije se k jeho identifikaci deskriptor souboru.

Tyto hodnoty jsou vždy použity pro stdin, stdout,a stderr:

  • 0 : standardní
  • 1 : standardní výstup
  • 2 : stderr

Reakce na kanály a přesměrování

Pro usnadnění úvodu někoho do předmětu je běžnou technikou naučit zjednodušenou verzi tématu. Například s gramatikou se nám říká, že pravidlo je „já před E, kromě po C.“ Ve skutečnosti však z tohoto pravidla existuje více výjimek než případů, které se jím řídí.

V podobném duchu, když mluví o stdin, stdouta stderr je vhodné do klusu ven přijímaný axiom, že proces ani neví ani starosti, kde jsou ukončeny její tři standardní proudy. Mělo by procesu záležet na tom, zda jeho výstup směřuje do terminálu nebo je přesměrován do souboru? Může dokonce zjistit, zda jeho vstup vychází z klávesnice nebo je do něj vložen z jiného procesu?

Proces ve skutečnosti ví - nebo alespoň může zjistit, zda se rozhodne zkontrolovat - a může odpovídajícím způsobem změnit své chování, pokud se autor softwaru rozhodl tuto funkci přidat.

Tuto změnu chování vidíme velmi snadno. Vyzkoušejte tyto dva příkazy:

je

ls | kočka

Na lspříkaz se chová jinak, pokud jeho výstup ( stdout) je odváděna do jiného příkazu. Jedná se o to,  lsže se přepne na výstup jednoho sloupce, nejde o převod provedený cat. A lsdělá to samé, pokud je přesměrován jeho výstup:

ls> capture.txt

cat capture.txt

Přesměrování stdout a stderr

Výhodou je, že chybové zprávy jsou doručovány vyhrazeným streamem. To znamená, že můžeme přesměrovat výstup příkazu ( stdout) do souboru a stderrv okně terminálu stále vidět všechny chybové zprávy ( ). Pokud potřebujete, můžete na chyby reagovat, jak se vyskytnou. Také zastaví chybové zprávy z kontaminace souboru, do kterého stdoutbyl přesměrován.

Zadejte následující text do editoru a uložte jej do souboru s názvem error.sh.

#! / bin / bash echo „Chystám se pokusit o přístup k souboru, který neexistuje“ cat bad-filename.txt

Vytvořte skript spustitelný pomocí tohoto příkazu:

chmod + x error.sh

První řádek skriptu odráží text do okna terminálu prostřednictvím  stdoutstreamu. Druhý řádek se pokusí získat přístup k souboru, který neexistuje. Tím se vygeneruje chybová zpráva doručená prostřednictvím stderr.

Spusťte skript pomocí tohoto příkazu:

./error.sh

Vidíme, že oba proudy výstupu, stdouta stderr, byly zobrazeny v oknech terminálu.

Zkusme přesměrovat výstup do souboru:

./error.sh> capture.txt

Chybová zpráva, která je doručena prostřednictvím, stderrje stále odeslána do okna terminálu. Můžeme zkontrolovat obsah souboru a zjistit, zda stdout výstup šel do souboru.

cat capture.txt

Výstup z stdinbyl podle očekávání přesměrován do souboru.

Symbol >přesměrování stdoutve výchozím nastavení funguje . Pomocí jednoho z numerických deskriptorů souborů můžete určit, který standardní výstupní proud chcete přesměrovat.

Chcete-li explicitně přesměrovat  stdout, použijte tuto instrukci přesměrování:

1>

Chcete-li explicitně přesměrovat  stderr, použijte tuto instrukci přesměrování:

2>

Zkusme náš test znovu a tentokrát použijeme 2>:

./error.sh 2> capture.txt

Chybová zpráva je přesměrována a stdoutechozpráva je odeslána do okna terminálu:

Podívejme se, co je v souboru capture.txt.

cat capture.txt

stderrZpráva je v capture.txt, jak se očekávalo.

Přesměrování jak stdout, tak stderr

Určitě, pokud můžeme přesměrovat jeden stdoutnebo stderrna soubor nezávisle na sobě, měli bychom být schopni je přesměrovat oba najednou, do dvou různých souborů?

Ano, můžeme. Tento příkaz bude směřovat stdoutdo souboru s názvem capture.txt a stderrdo souboru s názvem error.txt.

./error.sh 1> capture.txt 2> error.txt

Protože oba proudy výstupu - standardní výstup i standardní chyba - jsou přesměrovány do souborů, není v okně terminálu žádný viditelný výstup. Jsme vráceni na příkazový řádek, jako by se nic nestalo.

Podívejme se na obsah každého souboru:

cat capture.txt
kočka chyba.txt

Přesměrování stdout a stderr do stejného souboru

To je čisté, každý ze standardních výstupních toků jde do vlastního vyhrazeného souboru. Jedinou další kombinací, kterou můžeme udělat, je poslat oba stdouta stderrdo stejného souboru.

Můžeme toho dosáhnout pomocí následujícího příkazu:

./error.sh> capture.txt 2> & 1

Pojďme to rozebrat.

  • ./error.sh : Spustí soubor skriptu error.sh.
  • > capture.txt : Přesměruje stdoutstream do souboru capture.txt. >je zkratka pro 1>.
  • 2> & 1 : Toto používá instrukci &> přesměrování. Tato instrukce vám umožňuje říct prostředí, aby se jeden stream dostal do stejného cíle jako jiný stream. V tomto případě říkáme „redirect stream 2, stderrto the same destination that stream 1 stdout,, is redirected to.“

Neexistuje žádný viditelný výstup. To je povzbudivé.

Podívejme se na soubor capture.txt a podívejme se, co v něm je.

cat capture.txt

Jak stdouta stderrpotoky byly přesměrovány do jediného cílového souboru.

Chcete-li přesměrovat výstup proudu a tiše vyhodit, nasměrujte výstup na /dev/null.

Detekce přesměrování ve skriptu

Diskutovali jsme o tom, jak může příkaz zjistit, zda je některý ze streamů přesměrován, a podle toho může změnit své chování. Můžeme toho dosáhnout pomocí vlastních skriptů? Ano, můžeme. A je to velmi snadná technika pro pochopení a použití.

Zadejte následující text do editoru a uložte jej jako input.sh.

#! / bin / bash if [-t 0]; pak echo stdin přicházející z klávesnice, jinak echo stdin přicházející z potrubí nebo souboru fi

Pomocí následujícího příkazu jej spustíte:

chmod + x input.sh

Chytrou částí je test v hranatých závorkách. Volba -t(terminal) vrací true (0), pokud soubor spojený s deskriptorem souboru končí v okně terminálu. Jako argument k testu jsme použili deskriptor souboru 0, který představuje   stdin.

Pokud stdinje připojen k terminálovému oknu, test se ukáže jako pravdivý. Pokud stdinje připojen k souboru nebo kanálu, test selže.

Ke generování vstupu do skriptu můžeme použít jakýkoli vhodný textový soubor. Zde používáme jeden s názvem dummy.txt.

./input.sh <dummy.txt

Výstup ukazuje, že skript rozpozná, že vstup nepochází z klávesnice, pochází ze souboru. Pokud se rozhodnete, můžete podle toho změnit chování skriptu.

To bylo s přesměrováním souboru, zkusme to s trubkou.

kočičí dummy.txt | ./input.sh

Skript rozpozná, že se do něj pipetuje jeho vstup. Nebo přesněji rozpozná ještě jednou, že stdinstream není připojen k terminálovému oknu.

Spustíme skript bez rour ani přesměrování.

./input.sh

stdinProud je připojen k terminálu, a skript ohlásí to odpovídajícím způsobem.

Abychom zkontrolovali totéž s výstupním proudem, potřebujeme nový skript. Zadejte následující do editoru a uložte jej jako output.sh.

#! / bin / bash if [-t 1]; pak echo stdout jde do okna terminálu, jinak je echo stdout přesměrován nebo pipedován fi

Pomocí následujícího příkazu jej spustíte:

chmod + x input.sh

Jedinou významnou změnou tohoto skriptu je test v hranatých závorkách. K vyjádření deskriptoru souboru používáme číslici 1 stdout.

Zkusme to. Výstup projdeme potrubím cat.

./výstup | kočka

Skript rozpozná, že jeho výstup nepřechází přímo do okna terminálu.

Skript můžeme také otestovat přesměrováním výstupu do souboru.

./output.sh> capture.txt

Do okna terminálu není žádný výstup, jsme tiše vráceni do příkazového řádku. Jak bychom čekali.

Můžeme nahlédnout do souboru capture.txt, abychom zjistili, co bylo zachyceno. Použijte následující příkaz.

cat cat.sh

Jednoduchý test v našem skriptu opět zjistí, že stdoutstream není odesílán přímo do okna terminálu.

Pokud spustíme skript bez jakýchkoli kanálů nebo přesměrování, měl by zjistit, že stdoutse doručuje přímo do okna terminálu.

./output.sh

A to je přesně to, co vidíme.

Proudy vědomí

Znalost toho, jak zjistit, zda jsou vaše skripty připojeny k terminálovému oknu nebo k kanálu nebo jsou přesměrovány, vám umožní odpovídajícím způsobem upravit jejich chování.

Protokolovací a diagnostický výstup může být více či méně podrobný, v závislosti na tom, zda jde na obrazovku nebo do souboru. Chybové zprávy lze protokolovat do jiného souboru, než je normální výstup programu.

Obvykle více znalostí přináší více možností.