stdin, stdout og stderr er tre datastrømme, der oprettes, når du starter en Linux-kommando. Du kan bruge dem til at fortælle, om dine scripts sendes eller omdirigeres. Vi viser dig hvordan.
Indholdsfortegnelse
Streams forbinder to punkter
Så snart du begynder at lære om Linux og Unix-lignende operativsystemer, vil du støde på begreberne stdin, stdout og stederr. Disse er tre standardstrømme der etableres, når en Linux-kommando udføres. Inden for databehandling er en strøm noget, der kan overføre data. I tilfælde af disse strømme er disse data tekst.
Datastrømme har ligesom vandstrømme to ender. De har en kilde og en udstrømning. Uanset hvilken Linux-kommando du bruger giver den ene ende af hver stream. Den anden ende bestemmes af den shell, der lancerede kommandoen. Denne ende vil blive forbundet til terminalvinduet, forbundet til et rør eller omdirigeret til en fil eller anden kommando i henhold til den kommandolinje, der lancerede kommandoen.
Linux Standard Streams
I Linux er stdin standardinputstrømmen. Dette accepterer tekst som input. Tekstoutput fra kommandoen til shellen leveres via stdout-strømmen (standard ud). Fejlmeddelelser fra kommandoen sendes gennem stderr-strømmen (standardfejl).
Så du kan se, at der er to output-streams, stdout og stderr, og en input-stream, stdin. Fordi fejlmeddelelser og normal output hver har deres egen kanal til at føre dem til terminalvinduet, kan de håndteres uafhængigt af hinanden.
Streams håndteres som filer
Streams i Linux – som næsten alt andet – behandles som om de var filer. Du kan læse tekst fra en fil, og du kan skrive tekst ind i en fil. Begge disse handlinger involverer en strøm af data. Så konceptet med at håndtere en strøm af data som en fil er ikke så meget af en strækning.
Hver fil, der er knyttet til en proces, tildeles et unikt nummer for at identificere den. Dette er kendt som filbeskrivelsen. Når en handling skal udføres på en fil, filbeskrivelsen bruges til at identificere filen.
Disse værdier bruges altid til stdin, stdout og stderr:
0: stdin
1: standout
2: stderr
Reagerer på rør og omdirigeringer
For at lette nogens introduktion til et emne er en almindelig teknik at undervise i en forenklet version af emnet. For eksempel med grammatik får vi at vide, at reglen er “I før E, undtagen efter C.” Men faktisk der er flere undtagelser fra denne regel end der er tilfælde, der adlyder det.
På samme måde, når man taler om stdin, stdout og stderr, er det praktisk at tro det accepterede aksiom, at en proces hverken ved eller bekymrer sig om, hvor dens tre standardstrømme afsluttes. Skal en proces bekymre sig om dens output går til terminalen eller bliver omdirigeret til en fil? Kan den overhovedet se, om dens input kommer fra tastaturet eller bliver ledt ind i det fra en anden proces?
Faktisk ved en proces – eller i det mindste kan den finde ud af det, hvis den vælger at tjekke – og den kan ændre sin adfærd i overensstemmelse hermed, hvis softwareforfatteren besluttede at tilføje denne funktionalitet.
Vi kan meget let se denne ændring i adfærd. Prøv disse to kommandoer:
ls
ls | cat
ls-kommandoen opfører sig anderledes, hvis dens output (stdout) overføres til en anden kommando. Det er ls der skifter til en enkelt kolonne output, det er ikke en konvertering udført af cat. Og ls gør det samme, hvis dets output bliver omdirigeret:
ls > capture.txt
Omdirigerer stdout og stderr
Der er en fordel ved at have fejlmeddelelser leveret af en dedikeret stream. Det betyder, at vi kan omdirigere en kommandos output (stdout) til en fil og stadig se eventuelle fejlmeddelelser (stderr) i terminalvinduet. Du kan reagere på fejlene, hvis du har brug for det, efterhånden som de opstår. Det forhindrer også fejlmeddelelserne i at forurene filen, som stdout er blevet omdirigeret til.
Indtast følgende tekst i en editor og gem den i en fil kaldet error.sh.
#!/bin/bash echo "About to try to access a file that doesn't exist" cat bad-filename.txt
Gør scriptet eksekverbart med denne kommando:
chmod +x error.sh
Den første linje i scriptet ekko tekst til terminalvinduet via stdout-strømmen. Den anden linje forsøger at få adgang til en fil, der ikke eksisterer. Dette vil generere en fejlmeddelelse, der leveres via stderr.
Kør scriptet med denne kommando:
./error.sh
Vi kan se, at begge strømme af output, stdout og stderr, er blevet vist i terminalvinduerne.
Lad os prøve at omdirigere outputtet til en fil:
./error.sh > capture.txt
Outputtet fra stdin blev omdirigeret til filen som forventet.
> omdirigeringssymbolet fungerer som standard med stdout. Du kan bruge en af de numeriske filbeskrivelser til at angive, hvilken standard outputstrøm du ønsker at omdirigere.
For eksplicit at omdirigere stdout, brug denne omdirigeringsinstruktion:
1>
For eksplicit at omdirigere stderr, brug denne omdirigeringsinstruktion:
2>
Lad os prøve vores test igen, og denne gang bruger vi 2>:
./error.sh 2> capture.txt
Stderr-meddelelsen er i capture.txt som forventet.
Omdirigerer Både stdout og stderr
Hvis vi kan omdirigere enten stdout eller stderr til en fil uafhængigt af hinanden, burde vi vel være i stand til at omdirigere dem begge på samme tid til to forskellige filer?
Ja vi kan. Denne kommando vil dirigere stdout til en fil kaldet capture.txt og stderr til en fil kaldet error.txt.
./error.sh 1> capture.txt 2> error.txt
Lad os tjekke indholdet af hver fil:
cat capture.txt
cat error.txt
Omdirigerer stdout og stderr til den samme fil
Det er pænt, vi har fået hver af standard output-streams til at gå til sin egen dedikerede fil. Den eneste anden kombination, vi kan gøre, er at sende både stdout og stderr til den samme fil.
Vi kan opnå dette med følgende kommando:
./error.sh > capture.txt 2>&1
Lad os bryde det ned.
./error.sh: Starter scriptfilen error.sh.
> capture.txt: Omdirigerer stdout-strømmen til capture.txt-filen. > er en forkortelse for 1>.
2>&1: Dette bruger &> omdirigeringsinstruktionen. Denne instruktion giver dig mulighed for at fortælle skallen at få en strøm til at nå samme destination som en anden strøm. I dette tilfælde siger vi “omdiriger stream 2, stderr, til den samme destination, som stream 1, stdout, bliver omdirigeret til.”
Lad os tjekke capture.txt-filen og se, hvad der er i den.
cat capture.txt
Både stdout- og stderr-strømmene er blevet omdirigeret til en enkelt destinationsfil.
For at få outputtet fra en stream omdirigeret og stille smidt væk, skal du rette outputtet til /dev/null.
Registrering af omdirigering i et script
Vi diskuterede, hvordan en kommando kan registrere, om nogen af strømmene bliver omdirigeret, og kan vælge at ændre dens adfærd i overensstemmelse hermed. Kan vi opnå dette i vores egne scripts? Ja vi kan. Og det er en meget nem teknik at forstå og anvende.
Indtast følgende tekst i en editor og gem den som input.sh.
#!/bin/bash if [ -t 0 ]; then echo stdin coming from keyboard else echo stdin coming from a pipe or a file fi
Brug følgende kommando for at gøre det eksekverbart:
chmod +x input.sh
Den smarte del er test inden for de firkantede parenteser. Indstillingen -t (terminal) returnerer sand (0), hvis den fil, der er knyttet til filbeskrivelsen afsluttes i terminalvinduet. Vi har brugt filbeskrivelsen 0 som argumentet til testen, som repræsenterer stdin.
Hvis stdin er forbundet til et terminalvindue, vil testen vise sig at være sand. Hvis stdin er forbundet til en fil eller et rør, vil testen mislykkes.
Vi kan bruge enhver praktisk tekstfil til at generere input til scriptet. Her bruger vi en kaldet dummy.txt.
./input.shThe output shows that the script recognizes that the input isn’t coming from a keyboard, it is coming from a file. If you chose to, you could vary your script’s behavior accordingly.
That was with a file redirection, let’s try it with a pipe.
cat dummy.txt | ./input.shScriptet genkender, at dets input overføres til det. Eller mere præcist genkender den endnu en gang, at stdin-strømmen ikke er forbundet til et terminalvindue.
Lad os køre scriptet uden hverken pipes eller omdirigeringer.
./input.shStdin-strømmen er forbundet til terminalvinduet, og scriptet rapporterer dette i overensstemmelse hermed.
For at kontrollere det samme med outputstrømmen, har vi brug for et nyt script. Indtast følgende i en editor og gem det som output.sh.
#!/bin/bash if [ -t 1 ]; then echo stdout is going to the terminal window else echo stdout is being redirected or piped fiBrug følgende kommando for at gøre det eksekverbart:
chmod +x input.shDen eneste væsentlige ændring af dette script er i testen i de firkantede parenteser. Vi bruger tallet 1 til at repræsentere filbeskrivelsen for stdout.
Lad os prøve det. Vi sender udgangen gennem kat.
./output | catScriptet genkender, at dets output ikke går direkte til et terminalvindue.
Vi kan også teste scriptet ved at omdirigere outputtet til en fil.
./output.sh > capture.txtDer er intet output til terminalvinduet, vi vender lydløst tilbage til kommandoprompten. Som vi kunne forvente.
Vi kan se inde i capture.txt-filen for at se, hvad der blev fanget. Brug følgende kommando til at gøre det.
cat capture.shIgen, den simple test i vores script registrerer, at stdout-strømmen ikke sendes direkte til et terminalvindue.
Hvis vi kører scriptet uden pipes eller omdirigeringer, burde det registrere, at stdout bliver leveret direkte til terminalvinduet.
./output.shOg det er præcis, hvad vi ser.
Bevidsthedsstrømme
At vide, hvordan man kan se, om dine scripts er forbundet til terminalvinduet, eller et rør, eller bliver omdirigeret, giver dig mulighed for at justere deres adfærd i overensstemmelse hermed.
Logning og diagnostisk output kan være mere eller mindre detaljeret, afhængigt af om det går til skærmen eller til en fil. Fejlmeddelelser kan logges til en anden fil end den normale programoutput.
Som det normalt er tilfældet, giver mere viden flere muligheder.