Verward over stdin, stdout en stderr?

Ik ben nogal in de war met het doel van deze drie bestanden. Als ik het goed heb begrepen, is stdinhet bestand waarin een programma schrijft in zijn verzoeken om een taak in het proces uit te voeren, stdoutis het bestand waarin de kernel zijn output en het proces dat erom vraagt, heeft toegang tot de informatie van, en stderris het bestand waarin alle uitzonderingen worden ingevoerd. Bij het openen van deze bestanden om te controleren of deze daadwerkelijk voorkomen, vond ik niets dat dit suggereert!

Wat ik zou willen weten is wat precies het doel van deze bestanden is, absoluut afgestompt antwoord met heel weinig technisch jargon!


Antwoord 1, autoriteit 100%

Standaardinvoer– dit is de bestandshandledie uw proces leest om informatie van u te krijgen.

Standaard uitvoer– uw proces schrijft conventionele uitvoer naar deze bestandshandle.

Standaardfout– uw proces schrijft diagnostische uitvoer naar deze bestandshandle.

Dat is ongeveer net zo stom als ik het kan maken 🙂

Natuurlijk is dat meestal volgens afspraak. Er is niets dat u ervan weerhoudt om uw diagnostische informatie naar standaarduitvoer te schrijven als u dat wilt. U kunt zelfs de drie bestandshandvatten volledig sluiten en uw eigen bestanden openen voor I/O.

Wanneer uw proces start, zou het deze handvatten al moeten hebben geopend en kan het er gewoon van lezen en/of naar schrijven.

Standaard zijn ze waarschijnlijk verbonden met uw eindapparaat (bijv. /dev/tty), maar met shells kunt u verbindingen maken tussen deze handvatten en specifieke bestanden en/of apparaten ( of zelfs pijpleidingen naar andere processen) voordat uw proces begint (sommige van de mogelijke manipulaties zijn nogal slim).

Een voorbeeld is:

my_prog <inputfile 2>errorfile | grep XYZ

wat zal:

  • maak een proces voor my_prog.
  • open inputfileals uw standaardinvoer (bestandshandle 0).
  • open errorfileals uw standaardfout (bestandshandle 2).
  • maak een anderproces voor grep.
  • voeg de standaard uitvoer van my_progtoe aan de standaard invoer van grep.

Over uw opmerking:

Als ik deze bestanden in de map /dev open, hoe komt het dan dat ik nooit de uitvoer van een lopend proces te zien krijg?

Het is omdat het geen normale bestanden zijn. Hoewel UNIX allesergens als een bestand in een bestandssysteem presenteert, is dat op de laagste niveaus nog niet het geval. De meeste bestanden in de hiërarchie /devzijn teken- of blokapparaten, in feite een apparaatstuurprogramma. Ze hebben geen maat, maar ze hebben wel een hoofd- en een klein apparaatnummer.

Als je ze opent, ben je verbonden met het apparaatstuurprogramma in plaats van met een fysiek bestand, en het apparaatstuurprogramma is slim genoeg om te weten dat afzonderlijke processen afzonderlijk moeten worden afgehandeld.

Hetzelfde geldt voor het Linux /procbestandssysteem. Dat zijn geen echte bestanden, maar streng gecontroleerde gateways naar kernelinformatie.


Antwoord 2, autoriteit 24%

Het zou juister zijn om te zeggen dat stdin, stdouten stderreerder “I/O-streams” zijn
dan bestanden. Zoals je hebt opgemerkt, leven deze entiteiten niet in het bestandssysteem. Maar de
Unix-filosofie, voor zover het I/O betreft, is “alles is een bestand”. In praktijk,
dat betekent echt dat je dezelfde bibliotheekfuncties en interfaces kunt gebruiken (printf,
scanf, read, write, select, enz.) zonder dat u zich zorgen hoeft te maken of de I/O-stroom
is verbonden met een toetsenbord, een schijfbestand, een socket, een pijp of een andere I/O-abstractie.

De meeste programma’s moeten invoer-, schrijfuitvoer- en logfouten lezen, dus stdin, stdout,
en stderrzijn vooraf voor u gedefinieerd, als programmeergemak. Dit is alleen
een conventie en wordt niet afgedwongen door het besturingssysteem.


Antwoord 3, autoriteit 21%

Als aanvulling op de bovenstaande antwoorden, volgt hier een samenvatting van omleidingen:

EDIT: deze afbeelding is niet helemaal correct.

Het eerste voorbeeld gebruikt stdin helemaal niet, het geeft “hallo” door als argument voor het echo-commando.

In de afbeelding staat ook dat 2>&1 hetzelfde effect heeft als &> echter

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

Dit komt omdat &> vereist een bestand om naar door te verwijzen, en 2>&1 stuurt gewoon stderr naar stdout


Antwoord 4, autoriteit 9%

Ik ben bang dat je begrip volledig achterlijk is. 🙂

Denk aan “standaard in”, “standaard uit” en “standaardfout” vanuit het perspectief van het programma, niet vanuit het perspectief van de kernel.

Als een programma uitvoer moet afdrukken, drukt het normaal gesproken af naar “standaard uit”. Een programma drukt de uitvoer doorgaans af naar standard out met printf, dat ALLEEN naar standard out afdrukt.

Wanneer een programma foutinformatie nodig heeft (niet noodzakelijkerwijs uitzonderingen, zijn dat een programmeertaal-taalconstruct, opgelegd op een veel hoger niveau), wordt het normaal gesproken afdrukt naar “standaardfout”. Het doet normaal gesproken met fprintf, die een bestandstream accepteert om te gebruiken bij het afdrukken. De bestandstream kan elk bestand worden geopend voor het schrijven: Standaard-OUT, standaardfout of een ander bestand dat is geopend met fopenof fdopen.

“Standaard in” wordt gebruikt wanneer het bestand moet worden gelezen, met behulp van freadof fgetsof getchar.

Een van deze bestanden kan eenvoudig worden omgeleid van de schaal, zoals deze:

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

of, de hele enchilada:

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

Er zijn twee belangrijke voorbehoud: EERSTE, “Standaard in”, “Standard OUT”, en “standaardfout” slechts een conventie. Ze zijn een zeer sterk -conventie, maar het is allemaal slechts een overeenkomst die het erg leuk is om programma’s zoals deze te kunnen uitvoeren: grep echo /etc/services | awk '{print $2;}' | sorten laat de standaarduitgangen van elk programma verslaafd in de standaardinvoer van het volgende programma in de pijplijn.

Ten tweede heb ik de standaard ISO C-functies gegeven voor het werken met bestandsstromen (FILE *-objecten) — op kernelniveau zijn het allemaal bestandsdescriptors (intverwijzingen naar de bestandstabel) en veel lagere bewerkingen zoals readen write, die niet het gelukkige bufferen van de ISO C-functies doen. Ik dacht om het simpel te houden en de eenvoudigere functies te gebruiken, maar ik dacht toch dat je de alternatieven moest kennen. 🙂


Antwoord 5, autoriteit 4%

stdin

Lees invoer via de console (bijv. toetsenbordinvoer).
Gebruikt in C met scanf

scanf(<formatstring>,<pointer to storage> ...);

stdout

Produceert uitvoer naar de console.
Gebruikt in C met printf

printf(<string>, <values to print> ...);

stderr

Produceert ‘fout’-uitvoer naar de console.
Gebruikt in C met fprintf

fprintf(stderr, <string>, <values to print> ...);

Omleiding

De bron voor stdin kan worden omgeleid. In plaats van afkomstig te zijn van invoer via het toetsenbord, kan het bijvoorbeeld afkomstig zijn van een bestand (echo < file.txt), of een ander programma ( ps | grep <userid>).

De bestemmingen voor stdout, stderr kunnen ook worden omgeleid. Stdout kan bijvoorbeeld worden omgeleid naar een bestand: ls . > ls-output.txt, in dit geval wordt de uitvoer naar het bestand ls-output.txtgeschreven. Stderr kan worden omgeleidmet 2>.


Antwoord 6, autoriteit 4%

Ik denk dat mensen die zeggen dat stderralleen voor foutmeldingen mag worden gebruikt, misleidend zijn.

Het moet ook worden gebruikt voor informatieve berichten die bedoeld zijn voor de gebruiker die de opdracht uitvoert en niet voor potentiële stroomafwaartse gebruikers van de gegevens (dwz als u een shell-pipe uitvoert die verschillende opdrachten aan elkaar koppelt, wilt u geen informatieve berichten zoals “krijgen item 30 of 42424” om te verschijnen op stdoutomdat ze de consument in verwarring brengen, maar je wilt misschien toch dat de gebruiker ze ziet.

Zie ditvoor historische redenen:

“Alle programma’s plaatsten diagnostiek op de standaarduitgang. Dit had
veroorzaakte altijd problemen als de uitvoer naar een bestand werd omgeleid, maar
werd ondraaglijk toen de uitvoer naar een nietsvermoedende werd gestuurd
Verwerken. Niettemin, niet bereid om de eenvoud van de
standard-input-standard-output model, mensen tolereerden deze staat van
zaken via v6. Kort daarna sneed Dennis Ritchie de Gordian
knoop door het standaardfoutbestand te introduceren. Dat was niet helemaal genoeg.
Met pijpleidingen kan de diagnose afkomstig zijn van een van de verschillende programma’s
gelijktijdig lopen. Diagnostiek nodig om zichzelf te identificeren.”


Antwoord 7

Het gebruik van ps -aux onthult huidige processen, die allemaal worden vermeld in /proc/ als /proc/(pid)/, door cat /proc/(pid)/fd/0 aan te roepen, drukt het alles af dat wordt gevonden in de standaard output van dat proces denk ik. Dus misschien,

/proc/(pid)/fd/0 – Standaard uitvoerbestand
/proc/(pid)/fd/1 – Standaard invoerbestand
/proc/(pid)/fd/2 – Standaardfoutbestand

bijvoorbeeld

Maar werkte alleen zo goed voor /bin/bash, andere processen hadden over het algemeen niets in 0, maar veel hadden fouten geschreven in 2


Antwoord 8

Raadpleeg de man-pagina’s voor gezaghebbende informatie over deze bestanden, voer de opdracht op uw terminal uit.

$ man stdout 

Maar voor een eenvoudig antwoord is elk bestand voor:

stdout voor een stroom uit

stdin voor een stroom ingang

Stderr voor drukfouten of logberichten.

Elk UNIX-programma heeft elk van die streams.


Antwoord 9

Stderr zal geen IO-cachebuffering doen, dus als onze aanvraag kritieke berichtinfo (sommige fouten, uitzonderingen) moet afdrukken naar de console of om te gebruiken, gebruikt u het als het gebruik van algemene loginformatie als het gebruik IO-cachebuffering die er is, Een kans dat vóór het schrijven van onze berichten naar de toepassing van toepassing kan sluiten, waardoor de foutopsporingscomplex

blijft


Antwoord 10

Een bestand met bijbehorende buffering wordt een stroom genoemd en wordt gedeclareerd als een aanwijzer naar een gedefinieerd type bestand. De FOPEN-functie FOPEN () maakt bepaalde beschrijvende gegevens voor een stroom en retourneert een aanwijzer om de stroom in alle verdere transacties aan te wijzen. Normaal gesproken zijn er drie open streams met constante aanwijzers die in de kop worden gedeclareerd en geassocieerd met de standaard open bestanden.
Bij het opstarten van het programma zijn drie streams vooraf gedefinieerd en hoeven niet expliciet te worden geopend: standaardinvoer (voor het lezen van conventionele invoer), standaarduitvoer (voor het schrijven van conventionele uitvoer) en standaardfout (voor het schrijven van diagnostische uitgang). Wanneer geopend is de standaardfoutstroom niet volledig gebufferd; De standaardinvoer- en standaarduitvoerstromen zijn volledig gebufferd als en alleen als de stroom kan worden bepaald om niet naar een interactief apparaat te verwijzen

https://www.mksssoftware.com/docs/man5/stdio .5.asp


Antwoord 11

Hier is een lang artikel over stdin, stdouten stderr:

Om samen te vatten:

Streams worden behandeld als bestanden

Streams in Linux, zoals bijna al het andere, worden behandeld alsof het
het waren bestanden. U kunt tekst uit een bestand lezen en u kunt tekst schrijven
in een bestand. Bij beide acties gaat het om een stroom gegevens. Dus de
concept van het verwerken van een gegevensstroom als een bestand is niet zo’n groot probleem
strekken.

Elk bestand dat aan een proces is gekoppeld, krijgt een uniek nummer toegewezen aan
identificeer het. Dit staat bekend als de bestandsdescriptor. Wanneer een actie
moet worden uitgevoerd op een bestand, wordt de bestandsdescriptor gebruikt om
identificeer het bestand.

Deze waarden worden altijd gebruikt voor stdin, stdout en stderr:

0: stdin
1: stdout
2: stderr

Ironisch genoeg vond ik deze vraag over stack-overflow en het artikel hierboven omdat ik op zoek was naar informatie over abnormale/niet-standaard streams. Dus mijn zoektocht gaat door.

Other episodes