
stdin, stdout, en stderr zijn drie datastromen die worden gemaakt wanneer u een Linux-opdracht start. U kunt ze gebruiken om te zien of uw scripts worden doorgesluisd of omgeleid. We laten je zien hoe.
Streams voegen zich bij twee punten
Zodra je meer leert over Linux en Unix-achtige besturingssystemen, kom je de termen tegen stdin, stdout, en stederr. Dit zijn drie standaard streams die tot stand worden gebracht wanneer een Linux-opdracht wordt uitgevoerd. Bij computers is een stream iets dat gegevens kan overbrengen. In het geval van deze streams zijn die gegevens tekst.
Datastromen hebben, net als waterstromen, twee uiteinden. Ze hebben een bron en een uitstroom. Welke Linux-opdracht u ook gebruikt, biedt één uiteinde van elke stream. Het andere uiteinde wordt bepaald door de shell waarmee de opdracht is gestart. Dat uiteinde wordt verbonden met het terminalvenster, verbonden met een pijp of omgeleid naar een bestand of een andere opdracht, volgens de opdrachtregel die de opdracht heeft gestart.
De Linux Standard Streams
In Linux, stdin is de standaard invoerstroom. Dit accepteert tekst als invoer. Tekstuitvoer van het commando naar de shell wordt geleverd via de stdout (standaard uit) stream. Foutmeldingen van de opdracht worden verzonden via de stderr (standaardfout) stream.
U kunt dus zien dat er twee outputstromen zijn, stdout en stderr, en een invoerstroom, stdin. Omdat foutmeldingen en normale uitvoer elk hun eigen kanaal hebben om ze naar het terminalvenster te leiden, kunnen ze onafhankelijk van elkaar worden afgehandeld.
Streams worden behandeld als bestanden
Streams in Linux worden – net als bijna al het andere – behandeld alsof het bestanden zijn. U kunt tekst uit een bestand lezen en u kunt tekst in een bestand schrijven. Bij beide acties is een stroom gegevens betrokken. Dus het concept van het verwerken van een gegevensstroom als een bestand is niet zo heel ingewikkeld.
Elk bestand dat aan een proces is gekoppeld, krijgt een uniek nummer toegewezen om het te identificeren. Dit staat bekend als de bestandsdescriptor. Telkens wanneer een actie op een bestand moet worden uitgevoerd, wordt de bestandsdescriptor gebruikt om het bestand te identificeren.
Deze waarden worden altijd gebruikt voor stdin, stdout, en stderr:
- 0: stdin
- 1: stdout
- 2: stderr
Reageren op leidingen en omleidingen
Om iemands introductie tot een onderwerp te vergemakkelijken, is een veelgebruikte techniek het aanleren van een vereenvoudigde versie van het onderwerp. Met grammatica wordt ons bijvoorbeeld verteld dat de regel is “I voor E, behalve na C.” Maar eigenlijk zijn er meer uitzonderingen op deze regel dan dat er gevallen zijn die eraan voldoen.
In dezelfde geest, als we het er over hebben stdin, stdout, en stderr het is gemakkelijk om het geaccepteerde axioma uit te dragen dat een proces niet weet en ook niet kan schelen waar de drie standaardstromen worden beëindigd. Moet een proces zich zorgen maken of de uitvoer naar de terminal gaat of wordt omgeleid naar een bestand? Kan het zelfs zien of de invoer van het toetsenbord komt of vanuit een ander proces wordt ingevoerd?
In feite weet een proces het – of kan het er tenminste achter komen, mocht het ervoor kiezen om te controleren – en het kan zijn gedrag dienovereenkomstig veranderen als de softwareauteur besluit die functionaliteit toe te voegen.
We kunnen deze gedragsverandering heel gemakkelijk zien. Probeer deze twee opdrachten:
ls

ls | cat

De ls commando gedraagt zich anders als zijn output (stdout) wordt doorgesluisd naar een ander commando. Het is ls die overschakelt naar een uitvoer met één kolom, het is geen conversie uitgevoerd door cat. En ls doet hetzelfde als de uitvoer wordt omgeleid:
ls > capture.txt

Stdout en stderr omleiden
Er is een voordeel als foutmeldingen worden afgeleverd door een speciale stream. Het betekent dat we de uitvoer van een commando kunnen omleiden (stdout) naar een bestand en zie nog steeds eventuele foutmeldingen (stderr) in het terminalvenster. U kunt indien nodig op de fouten reageren zodra ze zich voordoen. Het voorkomt ook dat de foutmeldingen het bestand dat stdout is omgeleid naar.
Typ de volgende tekst in een editor en sla deze op in een bestand met de naam error.sh.
#!/bin/bash echo "About to try to access a file that doesn't exist" cat bad-filename.txt
Maak het script uitvoerbaar met deze opdracht:
chmod +x error.sh
De eerste regel van het script echoot tekst naar het terminalvenster, via de stdout stroom. De tweede regel probeert toegang te krijgen tot een bestand dat niet bestaat. Dit genereert een foutmelding die wordt afgeleverd via stderr.
Voer het script uit met deze opdracht:
./error.sh

We kunnen zien dat beide outputstromen, stdout en stderr, zijn weergegeven in de terminalvensters.

Laten we proberen de uitvoer om te leiden naar een bestand:
./error.sh > capture.txt

De output van stdin werd omgeleid naar het bestand zoals verwacht.

De > omleidingssymbool werkt met stdout standaard. U kunt een van de numerieke bestandsdescriptors gebruiken om aan te geven welke standaard uitvoerstroom u wilt omleiden.
Om expliciet om te leiden stdout, gebruik dan deze omleidingsinstructie:
1>
Om expliciet om te leiden stderr, gebruik dan deze omleidingsinstructie:
2>
Laten we het opnieuw proberen, en deze keer gebruiken we 2>:
./error.sh 2> capture.txt

De stderr bericht is in capture.txt zoals verwacht.

Omleiden van zowel stdout als stderr
Zeker, als we een van beide kunnen omleiden stdout of stderr naar een bestand onafhankelijk van elkaar, zouden we ze allebei tegelijkertijd naar twee verschillende bestanden moeten kunnen omleiden?
Ja dat kunnen we. Dit commando zal leiden stdout naar een bestand met de naam capture.txt en stderr naar een bestand met de naam error.txt.
./error.sh 1> capture.txt 2> error.txt

Laten we de inhoud van elk bestand controleren:
cat capture.txt
cat error.txt

Stdout en stderr omleiden naar hetzelfde bestand
Dat is netjes, we hebben elk van de standaard uitvoerstreams naar zijn eigen speciale bestand. De enige andere combinatie die we kunnen doen, is beide verzenden stdout en stderr naar hetzelfde bestand.
We kunnen dit bereiken met het volgende commando:
./error.sh > capture.txt 2>&1
Laten we dat opsplitsen.
- ./error.sh: Start het scriptbestand error.sh.
-
> capture.txt: Leidt het
stdoutstream naar het capture.txt-bestand.>is een afkorting voor1>. -
2> & 1: Dit gebruikt de &> redirect-instructie. Met deze instructie kun je de shell vertellen dat de ene stream naar dezelfde bestemming moet gaan als de andere stream. In dit geval zeggen we ‘redirect stream 2,
stderr, naar dezelfde bestemming die stream 1,stdout, wordt omgeleid naar. “

Laten we het capture.txt-bestand bekijken en kijken wat erin zit.
cat capture.txt

Beide stdout en stderr streams zijn omgeleid naar een enkel doelbestand.
Als u de uitvoer van een stream wilt laten omleiden en stilletjes wilt weggooien, richt u de uitvoer naar /dev/null.
Omleiding binnen een script detecteren
We hebben besproken hoe een commando kan detecteren of een van de streams wordt omgeleid, en ervoor kan kiezen om zijn gedrag dienovereenkomstig aan te passen. Kunnen we dit bereiken in onze eigen scripts? Ja dat kunnen we. En het is een heel gemakkelijke techniek om te begrijpen en toe te passen.
Typ de volgende tekst in een editor en sla deze op als input.sh.
#!/bin/bash if [ -t 0 ]; then echo stdin coming from keyboard else echo stdin coming from a pipe or a file fi
Gebruik de volgende opdracht om het uitvoerbaar te maken:
chmod +x input.sh
Het slimme is de test tussen de vierkante haken. De -t (terminal) optie retourneert true (0) als het bestand dat is gekoppeld aan de bestandsdescriptor eindigt in het terminalvenster. We hebben de bestandsdescriptor 0 gebruikt als het argument voor de test, wat staat voor stdin.
Als stdin is verbonden met een terminalvenster, zal de test waar blijken te zijn. Als stdin is verbonden met een bestand of een pijp, zal de test mislukken.
We kunnen elk handig tekstbestand gebruiken om invoer voor het script te genereren. Hier gebruiken we een genaamd dummy.txt.
./input.sh < dummy.txt

De uitvoer laat zien dat het script herkent dat de invoer niet van een toetsenbord komt, maar van een bestand. Als u ervoor kiest, kunt u het gedrag van uw script dienovereenkomstig aanpassen.

Dat was met een bestandsomleiding, laten we het proberen met een pijp.
cat dummy.txt | ./input.sh

Het script herkent dat zijn invoer erin wordt doorgesluisd. Of beter gezegd, het erkent nogmaals dat de stdin stream is niet verbonden met een terminalvenster.

Laten we het script uitvoeren zonder leidingen of omleidingen.
./input.sh

De stdin stream is verbonden met het terminalvenster en het script rapporteert dit dienovereenkomstig.
Om hetzelfde te controleren met de uitvoerstroom, hebben we een nieuw script nodig. Typ het volgende in een editor en sla het op als output.sh.
#!/bin/bash if [ -t 1 ]; then echo stdout is going to the terminal window else echo stdout is being redirected or piped fi
Gebruik de volgende opdracht om het uitvoerbaar te maken:
chmod +x input.sh
De enige significante wijziging in dit script is de test tussen vierkante haken. We gebruiken het cijfer 1 om de bestandsdescriptor voor te stellen stdout.
Laten we het uitproberen. We leiden de output door cat.
./output | cat

Het script herkent dat de uitvoer ervan niet rechtstreeks naar een terminalvenster gaat.

We kunnen het script ook testen door de uitvoer naar een bestand om te leiden.
./output.sh > capture.txt

We kunnen in het bestand capture.txt kijken om te zien wat er is vastgelegd. Gebruik hiervoor het volgende commando.
cat capture.sh

Nogmaals, de eenvoudige test in ons script detecteert dat het stdout stream wordt niet rechtstreeks naar een terminalvenster gestuurd.
Als we het script uitvoeren zonder leidingen of omleidingen, zou het dat moeten detecteren stdout wordt rechtstreeks in het terminalvenster afgeleverd.
./output.sh

En dat is precies wat we zien.

Bewustzijnsstromen
Als u weet of uw scripts zijn verbonden met het terminalvenster, of een pipe, of worden omgeleid, kunt u hun gedrag dienovereenkomstig aanpassen.
Logboekregistratie en diagnostische uitvoer kunnen meer of minder gedetailleerd zijn, afhankelijk van of het naar het scherm of naar een bestand gaat. Foutmeldingen kunnen worden gelogd naar een ander bestand dan de normale programma-uitvoer.
Zoals gewoonlijk brengt meer kennis meer mogelijkheden met zich mee.