¿Confundido sobre stdin, stdout y stderr?

230

Estoy bastante confundido con el propósito de estos tres archivos. Si mi interpretación es correcta, stdines el archivo en el que un programa escribe en sus peticiones para ejecutar una tarea en el proceso, stdoutes el archivo en el que el núcleo escribe su salida y el proceso solicitante tiene acceso a la información desde, y stderres el archivo en en el que se ingresan todas las excepciones. Al abrir estos archivos para verificar si realmente ocurren, ¡no encontré nada que sugiera eso!

Lo que me gustaría saber es cuál es exactamente el propósito de estos archivos, ¡una respuesta absolutamente tonta con muy poca jerga tecnológica!

Shouvik
fuente
36
Observación: Esta pregunta fue aceptable en 2010, pero hoy en día sería rechazada rápidamente.
byxor 01 de
3
@ Brandon ¿Puedes dar una razón? Creo que sería valioso para tu comentario.
Independiente
3
@byxor para ser justos, le preguntaré: ¿la publicación de Op solicitó a la gente que lo ayudara a depurar su código? parece que Shouvik hizo una pregunta sobre el propósito de stdin, stdout y stderr. La publicación del operador parece estar fuera de curiosidad, ¿no? (De hecho, estoy aprendiendo sobre esto yo mismo
cajero automático
2
@ user123456 tienes razón. Estaba aprendiendo a ser desarrollador de software y S / O en ese entonces era un gran lugar para aprender sobre programación. Originalmente pretendíamos que fuera un servicio wiki para todas las preguntas de ciencias de la computación. #juniorDevForLife
Shouvik
3
@ Shouvik gracias por ese poco de historia. También estoy aprendiendo a ser desarrollador de software (acabo de ser aceptado en un campamento genial en SF). Todavía soy bastante nuevo en S / O y todavía no estoy seguro de lo que puedo y no puedo publicar. Me parece que la moderación aquí puede ser bastante estricta. Me gusta esa etiqueta hash. #juniorDevForLife. Te enviaría un mensaje en lugar de comentar aquí, ya que esto no agrega nada a la discusión, pero no creo que S / O tenga un sistema pm. Que tengas un gran día.
Sansae

Respuestas:

251

Entrada estándar : este es el identificador de archivo que su proceso lee para obtener información de usted.

Salida estándar : su proceso escribe información normal en este identificador de archivo.

Error estándar : su proceso escribe información de error en este identificador de archivo.

Eso es casi tan tonto como puedo hacerlo :-)

Por supuesto, eso es principalmente por convención. No hay nada que le impida escribir su información de error en la salida estándar si lo desea. Incluso puede cerrar los tres controladores de archivos totalmente y abrir sus propios archivos para E / S.

Cuando comienza su proceso, ya debería tener estos identificadores abiertos y solo puede leerlos o escribirles.

De manera predeterminada, es probable que estén conectados a su dispositivo terminal (p. Ej. /dev/tty) , Pero los shells le permitirán configurar conexiones entre estos controladores y archivos y / o dispositivos específicos (o incluso canalizaciones a otros procesos) antes de que comience su proceso (algunos de las manipulaciones posibles son bastante inteligentes).

Un ejemplo es:

my_prog <inputfile 2>errorfile | grep XYZ

que lo hará:

  • crear un proceso para my_prog.
  • abrir inputfilecomo entrada estándar (identificador de archivo 0).
  • abrir errorfilecomo su error estándar (identificador de archivo 2).
  • crear otro proceso para grep.
  • adjunte la salida estándar de my_proga la entrada estándar de grep.

Re tu comentario:

Cuando abro estos archivos en la carpeta / dev, ¿cómo es que nunca puedo ver la salida de un proceso en ejecución?

Es porque no son archivos normales. Si bien UNIX presenta todo como un archivo en un sistema de archivos en algún lugar, eso no lo hace en los niveles más bajos. La mayoría de los archivos en la /devjerarquía son dispositivos de caracteres o bloques, efectivamente un controlador de dispositivo. No tienen un tamaño pero tienen un número de dispositivo mayor y menor.

Cuando los abre, está conectado al controlador del dispositivo en lugar de a un archivo físico, y el controlador del dispositivo es lo suficientemente inteligente como para saber que los procesos separados deben manejarse por separado.

Lo mismo es cierto para el sistema de /procarchivos de Linux . Esos no son archivos reales, solo puertas de enlace estrictamente controladas a la información del núcleo.

paxdiablo
fuente
1
Eso es por tu respuesta. Si bien puedo entender el propósito de los archivos de lo que usted describe, me gustaría avanzar un nivel más. cuando abro estos archivos en la carpeta / dev, ¿cómo es que nunca puedo ver la salida de un proceso en ejecución? Digamos que ejecuto top en el terminal, si se supone que no debe generar sus resultados en el archivo stdout periódicamente, por lo tanto, cuando se actualice, debería poder ver una instancia de la salida que se imprime en este archivo. Pero esto no es así. Estos archivos tampoco son iguales (los que están en el directorio / dev).
Shouvik el
77
Porque esos no son técnicamente archivos. Son nodos de dispositivo, que indican un dispositivo específico para escribir. UNIX puede presentarle todo como una abstracción de archivo, pero eso no lo hace en los niveles más profundos.
paxdiablo
1
Utilice la capacidad de redireccionamiento de shell. xyz >xyz.outescribirá su salida estándar en un archivo físico que otros procesos puedan leer. xyz | grep somethingconectará xyzstdout a grepstdin más directamente. Si desea acceso sin restricciones a un proceso que no controla de esa manera, deberá buscar algo parecido /proco escribir código para filtrar la salida conectándose de alguna manera al núcleo. Puede haber otras soluciones, pero probablemente todas sean tan peligrosas como las demás :-)
paxdiablo
20
@Shouvik, tenga en cuenta que /dev/stdines un enlace simbólico a /proc/self/fd/0: el primer descriptor de archivo que el programa que se está ejecutando actualmente ha abierto. Entonces, lo que señala /dev/stdincambiará de un programa a otro, porque /proc/self/siempre apunta al 'programa actualmente en ejecución'. (Cualquiera que sea el programa que esté haciendo la openllamada.) /dev/stdinY amigos fueron puestos allí para hacer que los scripts de shell setuid sean más seguros, y le permiten pasar el nombre /dev/stdinde archivo a programas que solo funcionan con archivos, pero que desea controlar de manera más interactiva. (Algún día será un truco útil para que lo sepas. :)
sarnold
1
@ CarlosW.Mercado, un archivo es una manifestación física de los datos. Por ejemplo, los bits almacenados en el disco duro. Un identificador de archivo es (generalmente) un pequeño token utilizado para referirse a ese archivo, una vez que lo ha abierto.
paxdiablo
62

Sería más correcto decir eso stdin, stdouty stderrson "secuencias de E / S" en lugar de archivos. Como habrás notado, estas entidades no viven en el sistema de archivos. Pero la filosofía de Unix, en lo que respecta a E / S, es "todo es un archivo". En la práctica, que realmente significa que se pueden utilizar las mismas funciones de biblioteca e interfaces ( printf, scanf, read, write, select, etc.) sin tener que preocuparse acerca de si la corriente I / O está conectado a un teclado, un archivo de disco, un enchufe, un tubo, o alguna otra abstracción de E / S.

La mayoría de los programas tienen que leer la entrada, la salida de escritura, y los errores de registro, por lo que stdin, stdouty stderrestán predefinidos para usted, para su conveniencia programación. Esto es solo una convención y el sistema operativo no lo aplica.

Jim Lewis
fuente
Gracias por tus aportes. ¿Sabrías cómo podría interceptar el flujo de datos de salida de un proceso y enviarlo a un archivo propio?
Shouvik
51

Como complemento de las respuestas anteriores, aquí hay un resumen sobre las redirecciones: Hoja de trucos de redireccionamiento

EDITAR: Este gráfico no es del todo correcto, pero no estoy seguro de por qué ...

Sin embargo, el gráfico dice que 2> & 1 tiene el mismo efecto que &>

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>
Leopold Gault
fuente
44
¡Su comentario combinado con la respuesta aceptada tiene mucho sentido y explica claramente las cosas! ¡Gracias!
Mykola
1
Una imagen vale mas que mil palabras !
tauseef_CuriousGuy
22

Me temo que tu comprensión es completamente al revés. :)

Piense en "entrada estándar", "salida estándar" y "error estándar" desde la perspectiva del programa , no desde la perspectiva del núcleo.

Cuando un programa necesita imprimir resultados, normalmente se imprime en "salida estándar". Un programa generalmente imprime la salida a la salida estándar printf, que imprime SOLAMENTE a la salida estándar.

Cuando un programa necesita imprimir información de error (no necesariamente excepciones, se trata de una construcción de lenguaje de programación, impuesta en un nivel mucho más alto), normalmente se imprime en "error estándar". Normalmente lo hace con fprintf, que acepta una secuencia de archivos para usar al imprimir. La secuencia de archivos podría ser cualquier archivo abierto para escritura: salida estándar, error estándar o cualquier otro archivo que se haya abierto con fopeno fdopen.

"estándar en" se usa cuando el archivo necesita leer la entrada, usando freado fgets, o getchar.

Cualquiera de estos archivos se puede redirigir fácilmente desde el shell, así:

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

O, toda la enchilada:

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

Hay dos advertencias importantes: Primero, "entrada estándar", "salida estándar" y "error estándar" son solo una convención. Son una convención muy fuerte , pero todo es solo un acuerdo de que es muy bueno poder ejecutar programas como este: grep echo /etc/services | awk '{print $2;}' | sorty tener las salidas estándar de cada programa conectadas a la entrada estándar del siguiente programa en la tubería.

En segundo lugar, he dado las funciones estándar ISO C para trabajar con secuencias de archivos ( FILE *objetos): en el nivel del núcleo, son todos los descriptores de archivos ( intreferencias a la tabla de archivos) y muchas operaciones de nivel inferior como ready write, que no hacer el búfer feliz de las funciones de ISO C. Pensé en hacerlo simple y usar las funciones más fáciles, pero de todos modos pensé que deberías conocer las alternativas. :)

sarnold
fuente
Entonces, cuando se ejecuta el proceso, escribe errores en este archivo stderr o cuando el programa se está compilando desde su origen. Además, cuando hablamos de estos archivos desde la perspectiva del compilador, ¿es diferente de cuando se compara con decir un programa?
Shouvik el
1
@Shouvik, el compilador es solo otro programa, con sus propios stdin, stdout y stderr. Cuando el compilador necesita escribir advertencias o errores, los escribirá en stderr. Cuando el compilador front-end emite un código intermedio para el ensamblador, podría escribir el código intermedio en stdout y el ensamblador podría aceptar su entrada en stdin, pero todo eso estaría detrás de escena desde su perspectiva como usuario.) Una vez que tenga un programa compilado, ese programa también puede escribir errores en su error estándar, pero no tiene nada que ver con ser compilado.
sarnold
Gracias por ese token de información. Supongo que es bastante estúpido de mi parte no verlo en esa perspectiva de todos modos ...: P
Shouvik
1
Así que usted está diciendo que nos ayuda estándar para imprimir el programa
babygame0ver
9

stdin

Lee la entrada a través de la consola (por ejemplo, entrada de teclado). Usado en C con scanf

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

stdout

Produce salida a la consola. Usado en C con printf

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

stderr

Produce salida de 'error' a la consola. Usado en C con fprintf

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

Redireccionamiento

La fuente de stdin se puede redirigir. Por ejemplo, en lugar de provenir de la entrada del teclado, puede provenir de un archivo ( echo < file.txt) u otro programa ( ps | grep <userid>).

Los destinos para stdout, stderr también se pueden redirigir. Por ejemplo, stdout se puede redirigir a un archivo: ls . > ls-output.txten este caso, la salida se escribe en el archivo ls-output.txt. Stderr puede ser redirigido con 2>.

mikek3332002
fuente
8

Creo que la gente que dice que stderrdebería usarse solo para mensajes de error es engañosa.

También debe usarse para mensajes informativos que están destinados al usuario que ejecuta el comando y no para los posibles consumidores posteriores de los datos (es decir, si ejecuta una tubería de shell que encadena varios comandos, no desea mensajes informativos como "obtener el elemento 30 de 42424 "para aparecer en stdout ya que confundirán al consumidor, pero es posible que aún desee que el usuario los vea.

Vea esto por razones históricas:

"Todos los programas colocaron diagnósticos en la salida estándar. Esto siempre causó problemas cuando la salida se redirigió a un archivo, pero se volvió intolerable cuando la salida se envió a un proceso desprevenido. Sin embargo, no estaba dispuesto a violar la simplicidad de la entrada estándar. modelo de salida estándar, la gente toleró este estado de cosas a través de v6. Poco después, Dennis Ritchie cortó el nudo gordiano introduciendo el archivo de error estándar. Eso no fue suficiente. Con las tuberías, el diagnóstico podría provenir de cualquiera de varios programas que se ejecutan simultáneamente. para identificarse ".

dee
fuente
3

El uso de ps -aux revela los procesos actuales, todos los cuales se enumeran en / proc / as / proc / (pid) /, al llamar a cat / proc / (pid) / fd / 0 imprime todo lo que se encuentra en la salida estándar de ese proceso creo. Así que tal vez,

/ proc / (pid) / fd / 0 - Archivo de salida estándar
/ proc / (pid) / fd / 1 - Archivo de entrada estándar
/ proc / (pid) / fd / 2 - Archivo de error estándar

por ejemplomi ventana de terminal

Pero solo funcionó bien para / bin / bash, otros procesos generalmente no tenían nada en 0, pero muchos tenían errores escritos en 2

Sam
fuente
3

Para obtener información autorizada sobre estos archivos, consulte las páginas de manual, ejecute el comando en su terminal.

$ man stdout 

Pero para una respuesta simple, cada archivo es para:

stdout para una salida

stdin para una entrada de flujo

stderr para imprimir errores o mensajes de registro.

Cada programa de Unix tiene cada una de esas transmisiones.

Margach Chris
fuente
2

stderr no realizará el almacenamiento en búfer de IO Cache, por lo que si nuestra aplicación necesita imprimir información crítica de mensajes (algunos errores, excepciones) para consolar o archivar, úsela donde use stdout para imprimir información de registro general, ya que utiliza el almacenamiento en búfer de IO Cache, existe la posibilidad de que antes de escribir nuestros mensajes a la aplicación de archivo puede cerrarse, dejando un complejo de depuración

geekanil
fuente
0

Un archivo con almacenamiento en búfer asociado se denomina flujo y se declara como un puntero a un tipo definido de ARCHIVO. La función fopen () crea ciertos datos descriptivos para una secuencia y devuelve un puntero para designar la secuencia en todas las transacciones posteriores. Normalmente hay tres secuencias abiertas con punteros constantes declarados en el encabezado y asociados con los archivos abiertos estándar. Al inicio del programa, tres flujos están predefinidos y no necesitan abrirse explícitamente: entrada estándar (para leer la entrada convencional), salida estándar (para escribir la salida convencional) y error estándar (para escribir la salida de diagnóstico). Cuando se abre, el flujo de error estándar no está completamente protegido; las secuencias de entrada y salida estándar están completamente almacenadas si y solo si se puede determinar que la secuencia no se refiere a un dispositivo interactivo

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

Bahruz Balabayov
fuente