Hva er stdin, stdout og stderr på Linux?

stdin,, stdoutog stderrer tre datastrømmer opprettet når du starter en Linux-kommando. Du kan bruke dem til å fortelle om manusene dine blir sendt eller omdirigert. Vi viser deg hvordan.

Strømmer blir to poeng

Så snart du begynner å lære om Linux og Unix-lignende operativsystemer, vil du komme over vilkårene stdin, stdoutog stederr. Dette er tre standardstrømmer som opprettes når en Linux-kommando kjøres. I databehandling er en strøm noe som kan overføre data. Når det gjelder disse strømningene, er disse dataene tekst.

Datastrømmer, som vannstrømmer, har to ender. De har en kilde og en utstrømning. Uansett hvilken Linux-kommando du bruker, gir den ene enden av hver strøm. Den andre enden bestemmes av skallet som startet kommandoen. Denne enden blir koblet til terminalvinduet, koblet til et rør, eller omdirigert til en fil eller annen kommando, i henhold til kommandolinjen som startet kommandoen.

Linux Standard Streams

I Linux  stdiner standard inngangsstrøm. Dette godtar tekst som input. Tekstutdata fra kommandoen til skallet leveres via stdout(standard ut) strømmen. Feilmeldinger fra kommandoen sendes gjennom stderr(standardfeil) strømmen.

Så du kan se at det er to output bekker, stdoutog stderr, og en inngang strøm, stdin. Fordi feilmeldinger og normal utgang hver har sin egen kanal for å føre dem til terminalvinduet, kan de håndteres uavhengig av hverandre.

Strømmer håndteres som filer

Strømmer i Linux - som nesten alt annet - blir behandlet som om de var filer. Du kan lese tekst fra en fil, og du kan skrive tekst i en fil. Begge disse handlingene involverer en datastrøm. Så konseptet med å håndtere en datastrøm som en fil er ikke så mye strekk.

Hver fil tilknyttet en prosess tildeles et unikt nummer for å identifisere den. Dette er kjent som filbeskrivelsen. Når det kreves at en handling utføres på en fil, brukes filbeskrivelsen til å identifisere filen.

Disse verdiene brukes alltid til stdin, stdout,og stderr:

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

Reagerer på rør og omdirigeringer

For å lette noens introduksjon til et emne, er en vanlig teknikk å lære en forenklet versjon av emnet. For eksempel, med grammatikk, blir vi fortalt at regelen er "Jeg før E, unntatt etter C." Men faktisk er det flere unntak fra denne regelen enn det er tilfeller som følger den.

På samme måte, når vi snakker om stdin, stdoutog stderr det er praktisk å trave ut akseptert aksiom at en prosess verken vet eller bryr seg hvor de tre standardstrømmer avsluttet. Bør en prosess bry seg om utdataene går til terminalen eller blir omdirigert til en fil? Kan den til og med fortelle om inngangen kommer fra tastaturet eller blir ledet inn i den fra en annen prosess?

Egentlig vet en prosess - eller i det minste den kan finne ut om den velger å sjekke - og den kan endre oppførselen tilsvarende hvis programvareforfatteren bestemte seg for å legge til den funksjonaliteten.

Vi kan se denne endringen i atferd veldig enkelt. Prøv disse to kommandoene:

ls

ls | katt

De lskommandoen oppfører seg annerledes hvis dens utgang ( stdout) blir transportert inn i en annen kommando. Det er  lssom bytter til en enkelt kolonneutgang, det er ikke en konvertering utført av cat. Og lsgjør det samme hvis produksjonen blir omdirigert:

ls> capture.txt

cat capture.txt

Omdirigere stdout og stderr

Det er en fordel å ha feilmeldinger levert av en dedikert strøm. Det betyr at vi kan omdirigere en kommandos utgang ( stdout) til en fil og fremdeles se eventuelle feilmeldinger ( stderr) i terminalvinduet. Du kan reagere på feilene hvis du trenger det, ettersom de oppstår. Det stopper også feilmeldingene fra å forurense filen som stdouter omdirigert til.

Skriv inn følgende tekst i en editor og lagre den i en fil som heter error.sh.

#! / bin / bash echo "Om å prøve å få tilgang til en fil som ikke eksisterer" cat bad-filename.txt

Gjør skriptet kjørbart med denne kommandoen:

chmod + x feil.sh

Den første linjen i skriptet ekko tekst til terminalvinduet via  stdoutstrømmen. Den andre linjen prøver å få tilgang til en fil som ikke eksisterer. Dette vil generere en feilmelding som leveres via stderr.

Kjør skriptet med denne kommandoen:

./error.sh

Vi kan se at begge strømmer for utdata stdoutog stderrhar blitt vist i terminalvinduene.

La oss prøve å omdirigere utdataene til en fil:

./error.sh> capture.txt

Feilmeldingen som leveres via stderrsendes fortsatt til terminalvinduet. Vi kan sjekke innholdet i filen for å se om stdout utdataene gikk til filen.

cat capture.txt

Utdataene fra stdinble omdirigert til filen som forventet.

Den >omdirigering symbol arbeider med stdoutsom standard. Du kan bruke en av de numeriske filbeskrivelsene til å indikere hvilken standard utgangsstrøm du vil omdirigere.

For å omdirigere eksplisitt  stdout, bruk denne viderekoblingsinstruksjonen:

1>

For å omdirigere eksplisitt  stderr, bruk denne viderekoblingsinstruksjonen:

2>

La oss prøve å teste igjen, og denne gangen bruker vi 2>:

./error.sh 2> capture.txt

Feilmeldingen blir omdirigert og stdoutechomeldingen sendes til terminalvinduet:

La oss se hva som er i capture.txt-filen.

cat capture.txt

Den stderrmeldingen er i capture.txt som forventet.

Omdirigering av både stdout og stderr

Hvis vi kan omdirigere en stdouteller stderrtil en fil uavhengig av hverandre, burde vi sikkert kunne omdirigere dem begge samtidig, til to forskjellige filer?

Ja vi kan. Denne kommandoen vil henvise stdouttil en fil som heter capture.txt og stderrtil en fil som heter error.txt.

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

Fordi begge strømmer av utgang - standard utgang og standard feil - blir omdirigert til filer, er det ingen synlig utgang i terminalvinduet. Vi kommer tilbake til ledeteksten som om ingenting har skjedd.

La oss sjekke innholdet i hver fil:

cat capture.txt
cat error.txt

Omdirigere stdout og stderr til samme fil

Det er pent, vi har hver av standardutgangsstrømmene til sin egen dedikerte fil. Den eneste andre kombinasjonen vi kan gjøre er å sende begge stdoutog stderrtil samme fil.

Vi kan oppnå dette med følgende kommando:

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

La oss bryte det ned.

  • ./error.sh : Starter skriptfilen error.sh.
  • > capture.txt : Omdirigerer stdoutstrømmen til capture.txt-filen. >er stenografi for 1>.
  • 2> & 1 : Dette bruker instruksjonen &> omdirigering. Denne instruksjonen lar deg fortelle skallet om å få en strøm til samme destinasjon som en annen strøm. I dette tilfellet sier vi "viderekobling av strøm 2 stderr, til samme destinasjon som strøm 1, stdoutblir omdirigert til."

Det er ingen synlig utgang. Det er oppmuntrende.

La oss sjekke capture.txt-filen og se hva som er i den.

cat capture.txt

Både streams stdoutog stderrstreams er omdirigert til en enkelt destinasjonsfil.

For å få utdataene fra en strøm omdirigert og kastet stille, rett utgangen til /dev/null.

Oppdage omdirigering i et skript

Vi diskuterte hvordan en kommando kan oppdage om noen av bekkene blir omdirigert, og kan velge å endre oppførselen tilsvarende. Kan vi oppnå dette i våre egne skript? Ja vi kan. Og det er en veldig enkel teknikk å forstå og bruke.

Skriv inn følgende tekst i en editor og lagre den som input.sh.

#! / bin / bash if [-t 0]; så ekko stdin kommer fra tastaturet ellers ekko stdin kommer fra et rør eller en fil fi

Bruk følgende kommando for å gjøre den kjørbar:

chmod + x input.sh

Den smarte delen er testen innenfor firkantede parenteser. Alternativet -t(terminal) returnerer true (0) hvis filen som er tilknyttet filbeskrivelsen, slutter i terminalvinduet. Vi har brukt filbeskrivelsen 0 som argumentet for testen, som representerer   stdin.

Hvis det stdiner koblet til et terminalvindu, vil testen vise seg å være sant. Hvis det stdiner koblet til en fil eller et rør, mislykkes testen.

Vi kan bruke hvilken som helst praktisk tekstfil til å generere input til skriptet. Her bruker vi en som heter dummy.txt.

./input.sh <dummy.txt

Utgangen viser at skriptet gjenkjenner at inngangen ikke kommer fra et tastatur, det kommer fra en fil. Hvis du valgte det, kan du variere skriptets oppførsel tilsvarende.

Det var med en filomdirigering, la oss prøve det med et rør.

cat dummy.txt | ./inngang.sh

Skriptet anerkjenner at innspillene blir sendt inn i det. Eller mer presist, det anerkjenner igjen at stdinstrømmen ikke er koblet til et terminalvindu.

La oss kjøre skriptet med verken rør eller omdirigeringer.

./inngang.sh

Den stdinstrøm er koblet til terminal-vinduet, og skriptet rapporterer denne tilsvarende.

For å sjekke det samme med utgangsstrømmen, trenger vi et nytt skript. Skriv inn følgende i en editor og lagre det som output.sh.

#! / bin / bash if [-t 1]; så går ekko stdout til terminalvinduet ellers blir ekko stdout omdirigert eller piped fi

Bruk følgende kommando for å gjøre den kjørbar:

chmod + x input.sh

Den eneste viktige endringen i dette skriptet er i testen i parentes. Vi bruker siffer 1 for å representere filbeskrivelsen for stdout.

La oss prøve det. Vi vil lede gjennomgangen cat.

./output | katt

Skriptet anerkjenner at utgangen ikke går direkte til et terminalvindu.

Vi kan også teste skriptet ved å omdirigere utdataene til en fil.

./output.sh> capture.txt

Det er ingen utdata til terminalvinduet, vi blir stille tilbake til ledeteksten. Som vi forventer.

Vi kan se inne i capture.txt-filen for å se hva som ble tatt. Bruk følgende kommando for å gjøre det.

cat capture.sh

Igjen, den enkle testen i skriptet oppdager at stdoutstrømmen ikke sendes direkte til et terminalvindu.

Hvis vi kjører skriptet uten noen rør eller omdirigeringer, skal det oppdage at stdoutdet blir levert direkte til terminalvinduet.

./output.sh

Og det er akkurat det vi ser.

Strømmer av bevissthet

Å vite hvordan du skal vite om manusene dine er koblet til terminalvinduet, eller et rør, eller blir omdirigert, lar deg justere oppførselen deres i samsvar med dette.

Logging og diagnostisk utgang kan være mer eller mindre detaljert, avhengig av om den går til skjermen eller til en fil. Feilmeldinger kan logges i en annen fil enn den normale programutgangen.

Som det vanligvis er tilfelle, gir mer kunnskap flere muligheter.