GNU/Linux >> Znalost Linux >  >> Linux

Jste zmateni ze stdin, stdout a stderr?

Správnější by bylo říci, že stdin , stdout a stderr jsou "I/O streamy" spíše než soubory. Jak jste si všimli, tyto entity nežijí v souborovém systému. Ale filozofie Unixu, pokud jde o I/O, je „všechno je soubor“. V praxi to opravdu znamená, že můžete používat stejné funkce a rozhraní knihovny (printf ,scanf , read , write , select , atd.), aniž byste se museli starat o to, zda je I/O stream připojen ke klávesnici, diskovému souboru, soketu, potrubí nebo nějaké jiné I/O abstrakci.

Většina programů potřebuje číst vstup, zapisovat výstup a protokolovat chyby, takže stdin , stdout a stderr jsou pro vás předdefinovány jako pohodlí při programování. Toto je pouze konvence a operační systém to nevynucuje.


Obávám se, že vaše chápání je zcela obrácené. :)

Představte si „standardní vstup“, „standardní výstup“ a „standardní chyba“ z programu z perspektivy, ne z pohledu jádra.

Když program potřebuje tisknout výstup, normálně tiskne na "standardní výstup". Program obvykle tiskne výstup na standardní výstup s printf , který tiskne POUZE na standardní výstup.

Když program potřebuje vytisknout informace o chybě (nemusí to být nutně výjimky, ty jsou konstruktem programovacího jazyka, vynuceným na mnohem vyšší úrovni), normálně vytiskne "standardní chybu". Normálně to dělá s fprintf , který přijímá datový proud souborů pro použití při tisku. Proud souboru může být jakýkoli soubor otevřený pro zápis:standardní výstup, standardní chyba nebo jakýkoli jiný soubor, který byl otevřen s fopen nebo fdopen .

"standardní" se používá, když soubor potřebuje číst vstup pomocí fread nebo fgets nebo getchar .

Kterýkoli z těchto souborů lze snadno přesměrovat z shellu takto:

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

Nebo celá enchilada:

cat < /etc/passwd > /tmp/out 2> /tmp/err

Existují dvě důležitá upozornění:Za prvé, „standardní vstup“, „standardní výstup“ a „standardní chyba“ jsou pouze konvence. Jsou velmi silné konvence, ale je to všechno jen dohoda, že je velmi hezké mít možnost spouštět programy jako je tento:grep echo /etc/services | awk '{print $2;}' | sort a mít standardní výstupy každého programu připojené ke standardnímu vstupu dalšího programu v kanálu.

Za druhé jsem uvedl standardní funkce ISO C pro práci se souborovými proudy (FILE * objekty) -- na úrovni jádra jsou to všechny deskriptory souborů (int odkazy na tabulku souborů) a operace na mnohem nižší úrovni, jako je read a write , které nedělají šťastné vyrovnávací paměti funkcí ISO C. Myslel jsem, že to bude jednoduché a použijem jednodušší funkce, ale přesto jsem si myslel, že byste měli znát alternativy. :)


Standardní vstup - toto je popisovač souboru který váš proces čte, aby od vás získal informace.

Standardní výstup - váš proces zapisuje konvenční výstup do tohoto popisovače souboru.

Standardní chyba - váš proces zapisuje diagnostický výstup do tohoto popisovače souboru.

To je asi tak hloupé, jak to dokážu :-)

Samozřejmě je to většinou konvencí. Pokud si přejete, nic vám nebrání zapisovat diagnostické informace na standardní výstup. Můžete dokonce úplně zavřít tři popisovače souborů a otevřít své vlastní soubory pro I/O.

Když se váš proces spustí, měl by již mít tyto úchyty otevřené a může z nich pouze číst a/nebo do nich zapisovat.

Ve výchozím nastavení jsou pravděpodobně připojeny k vašemu koncovému zařízení (např. /dev/tty ), ale shelly vám umožní nastavit spojení mezi těmito ovladači a konkrétními soubory a/nebo zařízeními (nebo dokonce kanály k jiným procesům) ještě před spuštěním vašeho procesu (některé možné manipulace jsou docela chytré).

Příkladem je:

my_prog <inputfile 2>errorfile | grep XYZ

který bude:

  • vytvořte proces pro my_prog .
  • otevřete inputfile jako standardní vstup (popis souboru 0).
  • otevřete errorfile jako standardní chyba (soubor popisovač 2).
  • vytvořit další proces pro grep .
  • připojte standardní výstup my_prog na standardní vstup grep .

K vašemu komentáři:

Když otevřu tyto soubory ve složce /dev, jak to, že nikdy neuvidím výstup běžícího procesu?

Je to proto, že to nejsou normální soubory. Zatímco UNIX představuje vše jako soubor někde v souborovém systému, na nejnižších úrovních to tak není. Většina souborů v /dev hierarchie jsou buď znaková nebo bloková zařízení, v podstatě ovladač zařízení. Nemají velikost, ale mají hlavní a vedlejší číslo zařízení.

Když je otevřete, jste připojeni k ovladači zařízení spíše než k fyzickému souboru a ovladač zařízení je dostatečně chytrý na to, aby věděl, že samostatné procesy by měly být zpracovávány samostatně.

Totéž platí pro Linux /proc souborový systém. To nejsou skutečné soubory, jen přísně kontrolované brány k informacím jádra.


Jako doplněk k výše uvedeným odpovědím je zde shrnutí přesměrování:

EDIT:Tato grafika není úplně správná.

První příklad vůbec nepoužívá stdin, předává "hello" jako argument příkazu echo.

Na obrázku je také uvedeno, že 2>&1 má stejný účinek jako &>, nicméně

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

Je to proto, že &> vyžaduje soubor k přesměrování a 2>&1 jednoduše posílá stderr do stdout


Linux
  1. Jak přesměrovat výstup do souboru a Stdout v Linuxu

  2. Výstup do Stdout a zároveň Grep do souboru?

  3. Co znamená propojení Stdout a Stdin?

  1. Způsob, jak přesměrovat výstup programu, a přesto jej přejít na Stdout?

  2. Proč Ls a Hexdump nesouhlasí s velikostí souboru?

  3. Patří zprávy o pokroku/protokolované informace na Stderr nebo Stdout?

  1. Zobrazit na obrazovce pouze Stderr, ale zapsat do souboru Stdout i Stderr?

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

  3. Jak přesměrovat stderr a stdout na různé soubory ve stejném řádku ve skriptu?