Confundido acerca de stdin, stdout y stderr?


Estoy bastante confundido con el propósito de estos tres archivos. Si mi comprensión es correcta, stdin es el archivo en el que un programa escribe en sus solicitudes para ejecutar una tarea en el proceso, stdout es el archivo en el que el núcleo escribe su salida y el proceso que lo solicita accede a la información, y stderr es el archivo en el que se introducen todas las excepciones. Al abrir estos archivos para verificar si realmente ocurren, no encontré nada que parezca sugerirlo.

Lo que yo quiere saber es ¿qué es exactamente el propósito de estos archivos, absolutamente atontada respuesta con muy poca tecnología jerga!

Author: Jonathan Leffler, 2010-08-02

10 answers

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

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

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

Eso es lo más tonto que puedo hacer: -)

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

Cuando su proceso comienza, ya debería tener estos controladores abiertos y solo puede leer y/o escribir en ellos.

De forma predeterminada, probablemente estén conectados a su dispositivo terminal (por ejemplo, /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 su proceso comienza (algunas de las manipulaciones posibles son bastante inteligentes).

Un ejemplo es:

my_prog <inputfile 2>errorfile | grep XYZ

Que será:

  • crea un proceso para my_prog.
  • abra inputfile como su entrada estándar (manejador de archivo 0).
  • abra errorfile como su error estándar (controlador de archivo 2).
  • crea otro proceso para grep.
  • conecte la salida estándar de my_prog a la entrada estándar de grep.

Re su comentario:

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

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

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 archivos Linux /proc. Esos no son archivos reales, solo puertas de enlace estrechamente controladas a la información del núcleo.

 159
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-11 04:19:26

Sería más correcto decir que stdin, stdout, y stderr son "flujos de E/S" más bien que los archivos. Como has notado, estas entidades no viven en el sistema de archivos. Pero el La filosofía de Unix, en lo que respecta a E/S, es "todo es un archivo". En la práctica, eso realmente significa que puede usar las mismas funciones e interfaces de biblioteca (printf, scanf, read, write, select, etc.) sin preocuparse de si el flujo de E/S está conectado a un teclado, un archivo de disco, un socket, una tubería o alguna otra abstracción de E / S.

La mayoría de los programas necesitan leer la entrada, escribir la salida y registrar errores, por lo que stdin, stdout, y stderr están predefinidos para usted, como una conveniencia de programación. Esto es sólo una convención, y no es aplicada por el sistema operativo.

 38
Author: Jim Lewis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-02 05:36:59

Me temo que su comprensión está completamente al revés. :)

Piense en "standard in", "standard out" y "standard error" desde la perspectiva del programa , no desde la perspectiva del núcleo.

Cuando un programa necesita imprimir la salida, normalmente imprime en "salida estándar". Un programa típicamente imprime la salida a salida estándar con printf, que imprime SOLO a salida estándar.

Cuando un programa necesita imprimir información de error (no necesariamente excepciones, esos son una construcción de lenguaje de programación, impuesta a un nivel mucho más alto), normalmente imprime a "error estándar". Normalmente lo hace con fprintf, que acepta un flujo de archivos para usar al imprimir. El flujo 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 fopen o fdopen.

"standard in" se usa cuando el archivo necesita leer input, usando fread o fgets, o getchar.

Cualquiera de estos archivos puede ser fácilmente redirigido 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 agradable poder ejecutar programas como este: grep echo /etc/services | awk '{print $2;}' | sort y tener las salidas estándar de cada programa conectadas a la entrada estándar del siguiente programa en el gasoducto.

En segundo lugar, he dado las funciones ISO C estándar para trabajar con flujos de archivos (objetosFILE *) at a nivel del núcleo, son todos los descriptores de archivos (int referencias a la tabla de archivos) y operaciones de nivel mucho más bajo como read y write, los que no hacen el buffering feliz de las funciones ISO C. Pensé en mantenerlo simple y usar las funciones más fáciles, pero pensé que de todos modos debería conocer las alternativas. :)

 20
Author: sarnold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-02 05:47:13

Como complemento de las respuestas anteriores, aquí hay un resumen sobre las redirecciones: Redirecciones cheatsheet

 13
Author: Leopold Gault,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-11 11:17:19

Stdin

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

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

Stdout

Produce la salida a la consola. Utilizado en C con printf

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

Stderr

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

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

Redirección

La fuente de stdin puede ser redirigida. 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.txt, en este caso la salida se escribe en el archivo ls-output.txt. Stderr se puede redirigir con 2>.

 7
Author: mikek3332002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-12 21:22:16

Usando ps-aux revela procesos actuales, todos los cuales están listados en /proc/ as /proc/(pid)/, llamando a cat /proc/(pid)/fd/0 imprime cualquier cosa que se encuentre 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 ejemploventana de mi 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

 3
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-27 00:16:04

Creo que la gente que dice que stderr debe 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 cualquier consumidor potencial de los datos (es decir, si ejecuta una tubería de shell encadenando varios comandos, no desea que aparezcan mensajes informativos como "getting item 30 of 42424" en la salida estándar, ya que confundirán al consumidor, pero aún puede querer que el usuario los vea.

Véase http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout para la justificación histórica:

"Todos los programas colocaron diagnósticos en la salida estándar. Este siempre había causado problemas cuando la salida se redirige a un archivo, pero se volvió insoportable cuando la salida fue enviado a un desprevenido proceso. Sin embargo, no dispuestos a violar la simplicidad del modelo estándar-entrada-estándar-salida, 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 de diagnóstico podría provenir de cualquiera de varios programas que se ejecutan simultáneamente. Diagnósticos necesarios para identificarse."

 2
Author: dee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-20 15:14:44

Stderr no hará almacenamiento en caché de IO, por lo que si nuestra aplicación necesita imprimir información crítica de mensajes (algunos errores ,excepciones) a la consola o al archivo, úselo donde use stdout para imprimir información general de registro mientras usa almacenamiento en caché de IO, existe la posibilidad de que antes de escribir nuestros mensajes en el archivo, la aplicación]}

 1
Author: geekanil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-13 14:02:13

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 de flujo

Stdin para una entrada de flujo

Stderr para errores de impresión o mensajes de registro.

Cada programa unix tiene cada una de esas secuencias.

 1
Author: Margach Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-17 14:58:46

Un archivo con buffering asociado se llama flujo y se declara como un puntero a un ARCHIVO de tipo definido. 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 flujos abiertos con punteros constantes declarados en el encabezado y asociados con los archivos abiertos estándar. Al iniciar el programa, tres flujos están predefinidos y no es necesario abrirlos explícitamente: entrada estándar (para leer entrada convencional), salida estándar (para escribir salida convencional) y error estándar (para escribir salida de diagnóstico). Cuando se abre el flujo de error estándar no está completamente almacenado en búfer; los flujos de entrada y salida estándar están completamente almacenados en búfer si y solo si se puede determinar que el flujo no se refiere a un dispositivo interactivo

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

 0
Author: Bahruz Balabayov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-28 13:57:35