Mis on stdin, stdout ja stderr Linuxis?

stdin, stdoutja stderr on kolm andmevoogu, mis luuakse Linuxi käsu käivitamisel. Nende abil saate öelda, kas teie skripte edastatakse või suunatakse ümber. Me näitame teile, kuidas.

Vood liituvad kahe punktiga

Niipea kui hakkate Linuxi ja Unixi-laadsete operatsioonisüsteemide kohta tundma õppima, jõuate terminitega kokku stdin, stdoutja stederr. Need on kolm standardset voogu, mis luuakse Linuxi käsu käivitamisel. Arvutamisel on voog midagi, mis võimaldab andmeid edastada. Nende voogude puhul on need andmed tekst.

Andmevoogudel, nagu ka veevoogudel, on kaks otsa. Neil on allikas ja väljavool. Ükskõik, millist Linuxi käsku te kasutate, tagab iga voo ühe otsa. Teise otsa määrab käsu käivitanud kest. See ots ühendatakse terminaliaknaga, ühendatakse toruga või suunatakse faili või muule käsule vastavalt käsu käivitanud käsureale.

Linuxi standardvood

Linuxisstdin on standardne sisendvoog. See aktsepteerib teksti sisendina. Tekstiväljund käsust shellile edastatakse stdout (standard välja) voog. Käsu tõrketeated saadetakse stderr (standardviga) voog.

Nii näete, et on kaks väljundvoogu, stdout ja stderrja üks sisendvoog, stdin. Kuna veateadetel ja tavalisel väljundil on klemmiaknasse kandmiseks oma kanal, saab neid käsitseda üksteisest sõltumatult.

Voogusid käsitletakse nagu faile

Linuxi vooge - nagu peaaegu kõike muud - koheldakse nagu faile. Saate failist teksti lugeda ja teksti faili kirjutada. Mõlemad toimingud hõlmavad andmevoogu. Nii et andmevoo failina käsitlemise kontseptsioon pole nii suur venitus.

Igale protsessiga seotud failile määratakse selle tuvastamiseks kordumatu number. Seda nimetatakse faili kirjeldajaks. Kui faili jaoks on vaja toimingut teha, kasutatakse faili tuvastamiseks faili kirjeldajat.

Neid väärtusi kasutatakse alati stdin, stdout, ja stderr:

  • 0: stdin
  • 1: stdout
  • 2: stderr

Torudele ja ümbersuunamistele reageerimine

Kellegi ainega tutvustamise hõlbustamiseks on levinud tehnika teema lihtsustatud versiooni õpetamine. Näiteks grammatika puhul öeldakse meile, et reegel on “Mina enne E, välja arvatud pärast C.” Kuid tegelikult on sellest reeglist rohkem erandeid kui juhtumeid, mis seda täidavad.

Sarnases mõttes, kui rääkida stdin, stdoutja stderr on mugav traavida aktsepteeritud aksioom, et protsess ei tea ega huvita, kus selle kolm standardset voogu lõpetatakse. Kas protsess peaks hoolima sellest, kas selle väljund läheb terminali või suunatakse faili? Kas ta suudab isegi öelda, kas selle sisend tuleb klaviatuurilt või sisestatakse seda mõne muu protsessi kaudu?

Tegelikult teab protsess - või vähemalt saab seda teada, kui ta peaks kontrollima - ja saab vastavalt oma käitumist muuta, kui tarkvara autor otsustas selle funktsiooni lisada.

Me näeme seda muutust käitumises väga lihtsalt. Proovige neid kahte käsku:

ls

ls | kass

The ls käsk käitub teisiti, kui selle väljund (stdout) sisestatakse teise käsu juurde. see onls mis lülitub ühe veeru väljundiks, pole see konversioon, mille teostab kass. Ja ls teeb sama asja, kui selle väljundit suunatakse ümber:

ls> lüüa.txt

kassi püüdmine.txt

Stdouti ja stderri ümbersuunamine

Spetsiaalse voo kaudu on veateadete eeliseks. See tähendab, et saame käsu väljundi ümber suunata (stdout) faili ja näete endiselt veateateid (stderr) terminaliaknas. Vigadele saate vajadusel reageerida, kui need ilmnevad. Samuti peatab see tõrketeadete selle faili saastamise stdout on ümber suunatud.

Sisestage järgmine tekst redaktorisse ja salvestage see faili nimega error.sh.

#! / bin / bash echo "Olemasolevale failile juurdepääsu proovimiseks" kass halb-failinimi.txt

Muutke skript selle käsuga käivitatavaks:

chmod + x error.sh

Skripti esimene rida kajas teksti terminaliaknassestdout voog. Teine rida proovib juurde pääseda failile, mida pole olemas. See loob veateate, mis edastatakse kaudu stderr.

Käivitage skript selle käsuga:

./error.sh

Näeme, et mõlemad väljundvood, stdout ja stderron kuvatud terminaliakendes.

Proovime suunata väljund faili:

./error.sh> capture.txt

Kaudu edastatud veateade stderr saadetakse ikka terminaliaknasse. Saame kontrollida faili sisu, et näha, kas stdout väljund läks faili.

kassi püüdmine.txt

Väljund stdin suunati faili vastavalt ootustele.

The > ümbersuunamise sümbol töötab stdout algselt. Ühe numbrilise failikirjeldaja abil saate näidata, millist standardset väljundvoogu soovite ümber suunata.

Selgesõnaliselt ümbersuunamiseks stdout, kasutage seda ümbersuunamisjuhist:

1>

Selgesõnaliselt ümbersuunamiseks stderr, kasutage seda ümbersuunamisjuhist:

2>

Proovime uuesti proovida ja seekord kasutame 2>:

./error.sh 2> capture.txt

Veateade suunatakse ümber ja stdoutkaja sõnum saadetakse terminaliaknasse:

Vaatame, mis on failis capture.txt.

kassi püüdmine.txt

The stderr sõnum on ootuspäraselt capt.txt-s.

Nii stdout kui stderr ümbersuunamine

Kindlasti, kui suudame kumbagi ümber suunata stdout või stderr faili üksteisest sõltumatult, peaksime saama neid mõlemat korraga ümber suunata kahte erinevasse faili?

Jah me saame. See käsk suunab stdout faili nimega capture.txt ja stderr faili nimega error.txt.

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

Kuna mõlemad väljundvood - standardväljund ja standardviga - suunatakse failidesse, pole terminaliaknas nähtavat väljundit. Me naaseme käsurea viipale, nagu poleks midagi juhtunud.

Kontrollime iga faili sisu:

kassi püüdmine.txt
kassi viga.txt

Stdouti ja stderri ümbersuunamine samasse faili

See on kena, meil on kõik tavalised väljundvood oma spetsiaalsesse faili. Ainus teine ​​kombinatsioon, mida saame teha, on saata mõlemad stdout ja stderr samasse faili.

Selle saavutame järgmise käsuga:

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

Lahustame selle.

  • ./error.sh: Käivitab skriptifaili error.sh.
  • > lüüa.txt: Suunab stdout voog faili capture.txt. > on lühikirjeldus 1>.
  • 2>&1: See kasutab käsku &> ümbersuunamine. See juhis võimaldab teil öelda kestale, et üks voog jõuaks teise vooga samasse sihtkohta. Sel juhul ütleme „suunake voog 2 ümber, stderr, samasse sihtkohta, mis voog 1, stdout, suunatakse aadressile. "

Nähtavat väljundit pole. See on julgustav.

Kontrollime faili capture.txt ja näeme, mis selles on.

kassi püüdmine.txt

Mõlemad stdout ja stderr voogud on suunatud ühte sihtfaili.

Voo väljundi ümbersuunamiseks ja hääletuks viskamiseks suunake väljund / dev / null.

Ümbersuunamise tuvastamine skripti sees

Arutasime, kuidas käsk suudab tuvastada, kas mõnda voogu suunatakse ümber, ja saame oma käitumist vastavalt muuta. Kas me saame seda oma skriptide abil saavutada? Jah me saame. Ja seda on väga lihtne mõista ja rakendada.

Sisestage järgmine tekst redaktorisse ja salvestage see sisendina.sh.

#! / bin / bash kui [-t 0]; siis klaviatuurilt tulev kaja-stdin mujalt torust või faili-fi-st tulev kaja-stdin

Selle käivitamiseks kasutage järgmist käsku:

chmod + x sisend.sh

Nutikas osa on katse nurksulgudes. The -t (terminal) tagastab väärtuse true (0), kui failikirjeldajaga seotud fail lõpeb terminaliaknas. Testi argumendina kasutasime faili kirjeldajat 0, mis esindabstdin.

Kui stdin on terminali aknaga ühendatud, osutub test tõeseks. Kui stdin on faili või toruga ühendatud, test ebaõnnestub.

Skripti sisendi loomiseks võime kasutada mis tahes mugavat tekstifaili. Siin kasutame ühte nime dummy.txt.

./input.sh <näiv.txt

Väljund näitab, et skript tuvastab, et sisend ei pärine klaviatuurilt, vaid failist. Kui otsustate, võite vastavalt oma skripti käitumist muuta.

See oli faili ümbersuunamisega, proovime seda toruga.

kass mannekeen.txt | ./input.sh

Skript tunnistab, et sinna sisestatakse selle sisend. Või täpsemalt, ta tunnistab veel kord, et stdin voog pole terminaliaknaga ühendatud.

Käivitame skripti ilma torude ega ümbersuunamisteta.

./input.sh

The stdin voog on ühendatud terminaliaknaga ja skript teatab sellest vastavalt.

Sama asja kontrollimiseks väljundvooga vajame uut skripti. Sisestage redaktorisse järgmine ja salvestage see väljundina.sh.

#! / bin / bash kui [-t 1]; siis läheb kaja stdout terminaliaknasse, muidu suunatakse kaja stdout ümber või torustatakse fi

Selle käivitamiseks kasutage järgmist käsku:

chmod + x sisend.sh

Ainus oluline muudatus selles skriptis on nurksulgudes olev test. Kasutame faili kirjeldaja tähistamiseks numbrit 1 stdout.

Proovime järele. Me juhime väljundi läbi kass.

./väljund | kass

Skript tunnistab, et selle väljund ei lähe otse terminaliaknasse.

Samuti saame skripti testida, suunates väljundi faili.

./output.sh> capture.txt

Terminali aknas pole väljundit, meid naastakse vaikides käsureale. Nagu me eeldaksime.

Saame vaadata faili capture.txt sisse, et näha, mis on jäädvustatud. Selleks kasutage järgmist käsku.

kassi püüdmine.sh

Jällegi tuvastab meie skripti lihtne test, et stdout voogu ei saadeta otse terminaliaknasse.

Kui käivitame skripti ilma torude või ümbersuunamisteta, peaks see selle tuvastama stdout tarnitakse otse terminaliaknasse.

./output.sh

Ja seda me täpselt näeme.

Teadvusevood

Teadmine, kuidas teada saada, kas teie skriptid on terminali akna või toruga ühendatud või suunatakse ümber, võimaldab teil nende käitumist vastavalt kohandada.

Logi ja diagnostika väljund võib olla enam-vähem üksikasjalik, olenevalt sellest, kas see läheb ekraanile või faili. Veateateid saab logida muusse faili kui tavaline programmi väljund.

Nagu tavaliselt, annab rohkem teadmisi rohkem võimalusi.