GNU/Linux >> Tutoriales Linux >  >> Linux

¿Confundido acerca de stdin, stdout y stderr?

Sería más correcto decir que stdin , stdout y stderr son "flujos de E/S" en lugar de archivos. Como habrá notado, estas entidades no viven en el sistema de archivos. Pero la filosofía de Unix, en lo que se refiere 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 zócalo, una tubería o alguna otra abstracción de E/S.

La mayoría de los programas necesitan leer entradas, escribir salidas y registrar errores, así que stdin , stdout y stderr están predefinidos para usted, como una conveniencia de programación. Esta es solo una convención y el sistema operativo no la aplica.


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

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

Cuando un programa necesita imprimir resultados, normalmente imprime a "salida estándar". Un programa normalmente imprime la salida a la salida estándar con printf , que imprime SÓLO en la salida estándar.

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

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

Cualquiera de estos archivos se puede redirigir fácilmente. del caparazón, 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 la enchilada entera:

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 muy fuertes convención, pero todo es solo un acuerdo de que es muy bueno 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 la canalización.

En segundo lugar, le he proporcionado las funciones ISO C estándar para trabajar con secuencias de archivos (FILE * objetos) -- a nivel del kernel, son todos los descriptores de archivos (int referencias a la tabla de archivos) y operaciones de mucho más bajo nivel como read y write , que no realizan el feliz almacenamiento en búfer de las funciones ISO C. Pensé en mantenerlo simple y usar las funciones más fáciles, pero pensé que de todos modos deberías conocer las alternativas. :)


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 una salida convencional en este identificador de archivo.

Error estándar - su proceso escribe la salida de diagnóstico en este identificador de archivo.

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

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

Cuando comience su proceso, ya debería tener estos identificadores 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 identificadores y archivos y/o dispositivos específicos (o incluso canalizaciones a otros procesos) antes de que comience su proceso (algunas de las manipulaciones posibles son bastante inteligentes).

Un ejemplo es:

my_prog <inputfile 2>errorfile | grep XYZ

que:

  • crear un proceso para my_prog .
  • abrir inputfile como su entrada estándar (identificador de archivo 0).
  • abrir errorfile como su error estándar (identificador de archivo 2).
  • crear otro proceso para grep .
  • adjunte la salida estándar de my_prog a la entrada estándar de grep .

Re tu comentario:

Cuando abro estos archivos en la carpeta /dev, ¿cómo es que nunca puedo ver el resultado 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 significa que sea así en los niveles más bajos. La mayoría de los archivos en el /dev jerarquía son dispositivos de caracteres o de bloque, efectivamente un controlador de dispositivo. No tienen un tamaño pero sí 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 Linux /proc sistema de archivos Esos no son archivos reales, solo puertas de enlace estrictamente controladas a la información del kernel.


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

EDITAR:Este gráfico no es del todo correcto.

El primer ejemplo no usa stdin en absoluto, está pasando "hola" como argumento al comando echo.

El gráfico también dice que 2>&1 tiene el mismo efecto que &> sin embargo

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

Esto se debe a que &> requiere un archivo para redirigir, y 2>&1 simplemente envía stderr a stdout


Linux
  1. Cómo redirigir la salida a un archivo y salida estándar en Linux

  2. ¿Qué significa conectar Stdout y Stdin?

  3. ¿Por qué Ls y Hexdump no están de acuerdo sobre el tamaño del archivo?

  4. ¿Los informes de progreso/la información de registro pertenecen a Stderr o Stdout?

  5. ¿Mostrar solo Stderr en pantalla pero escribir tanto Stdout como Stderr en el archivo?

Cómo redirigir stderr a stdout en Bash

¿Qué forma de redirigir la salida de un programa y todavía hacer que vaya a la salida estándar?

¿Cómo redirigir stderr y stdout a diferentes archivos en la misma línea en el script?

Canalización de stdout y stderr dentro de una regla Makefile

Restaurar stdout y stderr al valor predeterminado

¿Es posible que el descriptor de archivo de Linux 0 1 2 no sea para stdin, stdout y stderr?