¿Qué son stdin, stdout y stderr en Linux?

Publicado: 2022-01-29
Ventana de terminal en una computadora con Linux
Fatmawati Achmad Zaenuri/Shutterstock.com

stdin , stdout y stderr son tres flujos de datos creados cuando ejecuta un comando de Linux. Puede usarlos para saber si sus scripts están siendo canalizados o redirigidos. Te mostramos cómo.

Las corrientes unen dos puntos

Tan pronto como comience a aprender acerca de los sistemas operativos Linux y similares a Unix, se encontrará con los términos stdin , stdout y stederr . Estos son tres flujos estándar que se establecen cuando se ejecuta un comando de Linux. En informática, un flujo es algo que puede transferir datos. En el caso de estos flujos, esos datos son texto.

Los flujos de datos, como los flujos de agua, tienen dos extremos. Tienen una fuente y una salida. Cualquiera que sea el comando de Linux que esté usando proporciona un extremo de cada flujo. El otro extremo está determinado por el shell que lanzó el comando. Ese extremo se conectará a la ventana de terminal, se conectará a una canalización o se redirigirá a un archivo u otro comando, según la línea de comando que inició el comando.

Los flujos estándar de Linux

En Linux, stdin es el flujo de entrada estándar. Esto acepta texto como su entrada. La salida de texto del comando al shell se entrega a través de la transmisión stdout (salida estándar). Los mensajes de error del comando se envían a través de la secuencia stderr (error estándar).

Entonces puede ver que hay dos flujos de salida, stdout y stderr , y un flujo de entrada, stdin . Debido a que los mensajes de error y la salida normal tienen cada uno su propio conducto para llevarlos a la ventana del terminal, se pueden manejar de forma independiente.

Las transmisiones se manejan como archivos

Los flujos en Linux, como casi todo lo demás, se tratan como si fueran archivos. Puede leer texto de un archivo y puede escribir texto en un archivo. Ambas acciones implican un flujo de datos. Entonces, el concepto de manejar un flujo de datos como un archivo no es tan exagerado.

Anuncio publicitario

A cada archivo asociado con un proceso se le asigna un número único para identificarlo. Esto se conoce como el descriptor de archivo. Siempre que se requiere realizar una acción en un archivo, el descriptor de archivo se utiliza para identificar el archivo.

Estos valores siempre se usan para stdin , stdout, y stderr :

  • 0 : entrada estándar
  • 1 : salida estándar
  • 2 : estándar

Reacción a canalizaciones y redireccionamientos

Para facilitar la introducción de alguien a un tema, una técnica común es enseñar una versión simplificada del tema. Por ejemplo, con la gramática, se nos dice que la regla es "I antes de E, excepto después de C". Pero en realidad, hay más excepciones a esta regla que casos que la obedecen.

De manera similar, cuando se habla de stdin , stdout y stderr , es conveniente sacar a relucir el axioma aceptado de que un proceso no sabe ni le importa dónde terminan sus tres flujos estándar. ¿Debería importarle a un proceso si su salida va a la terminal o se redirige a un archivo? ¿Puede incluso decir si su entrada proviene del teclado o se está canalizando desde otro proceso?

En realidad, un proceso sabe, o al menos puede averiguarlo, si decide verificarlo, y puede cambiar su comportamiento en consecuencia si el autor del software decide agregar esa funcionalidad.

Anuncio publicitario

Podemos ver este cambio en el comportamiento muy fácilmente. Prueba estos dos comandos:

 ls 

 ls | gato 

El comando ls se comporta de manera diferente si su salida ( stdout ) se canaliza a otro comando. Es ls el que cambia a una salida de una sola columna, no es una conversión realizada por cat . Y ls hace lo mismo si se redirige su salida:

 ls > capturar.txt 

 captura de gato.txt 

Redirigir stdout y stderr

Hay una ventaja en tener mensajes de error entregados por un flujo dedicado. Significa que podemos redirigir la salida de un comando ( stdout ) a un archivo y seguir viendo cualquier mensaje de error ( stderr ) en la ventana del terminal. Puede reaccionar a los errores si es necesario, a medida que ocurren. También evita que los mensajes de error contaminen el archivo al que se stdout la salida estándar.

Escriba el siguiente texto en un editor y guárdelo en un archivo llamado error.sh.

 #!/bin/bash

echo "A punto de intentar acceder a un archivo que no existe"
cat bad-filename.txt

Haga que el script sea ejecutable con este comando:

 chmod +x error.sh

La primera línea de la secuencia de comandos hace eco del texto en la ventana del terminal, a través de la secuencia de stdout . La segunda línea intenta acceder a un archivo que no existe. Esto generará un mensaje de error que se envía a través de stderr .

Ejecute el script con este comando:

 ./error.sh 

Podemos ver que ambos flujos de salida, stdout y stderr , se han mostrado en las ventanas de la terminal.

Intentemos redirigir la salida a un archivo:

 ./error.sh > capturar.txt 

Anuncio publicitario

El mensaje de error que se entrega a través de stderr todavía se envía a la ventana de la terminal. Podemos verificar el contenido del archivo para ver si la stdout estándar fue al archivo.

 captura de gato.txt 

La salida de stdin se redirigió al archivo como se esperaba.

El símbolo de redirección > funciona con la stdout estándar de forma predeterminada. Puede utilizar uno de los descriptores de archivo numéricos para indicar qué flujo de salida estándar desea redirigir.

Para redirigir explícitamente stdout , use esta instrucción de redirección:

 1>

Para redirigir explícitamente stderr , use esta instrucción de redirección:

 2>

Intentemos nuestra prueba nuevamente, y esta vez usaremos 2> :

 ./error.sh 2> capturar.txt 

El mensaje de error se redirige y el mensaje de echo de stdout estándar se envía a la ventana del terminal:

Veamos qué hay en el archivo capture.txt.

 captura de gato.txt 

El mensaje stderr está en capture.txt como se esperaba.

Redirigir tanto stdout como stderr

Seguramente, si podemos redirigir stdout o stderr a un archivo independientemente uno del otro, ¿deberíamos poder redirigir ambos al mismo tiempo, a dos archivos diferentes?

Anuncio publicitario

Si podemos. Este comando dirigirá stdout a un archivo llamado capture.txt y stderr a un archivo llamado error.txt.

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

Debido a que ambos flujos de salida (salida estándar y error estándar) se redireccionan a archivos, no hay salida visible en la ventana del terminal. Volvemos a la línea de comandos como si nada hubiera ocurrido.

Veamos el contenido de cada archivo:

 captura de gato.txt
 error de gato.txt 

Redirigir stdout y stderr al mismo archivo

Eso está bien, tenemos cada uno de los flujos de salida estándar yendo a su propio archivo dedicado. La única otra combinación que podemos hacer es enviar tanto stdout como stderr al mismo archivo.

Esto lo podemos lograr con el siguiente comando:

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

Analicemos eso.

  • ./error.sh : inicia el archivo de script error.sh.
  • > capture.txt : Redirige el flujo de salida estándar al archivo stdout . > es la abreviatura de 1> .
  • 2>&1 : Esto usa la instrucción de redirección &>. Esta instrucción le permite decirle al shell que haga que un flujo llegue al mismo destino que otro flujo. En este caso, estamos diciendo "redirigir el flujo 2, stderr , al mismo destino al que se está redirigiendo el flujo 1, stdout ".

No hay salida visible. Eso es alentador.

Revisemos el archivo capture.txt y veamos qué contiene.

 captura de gato.txt 

Los flujos stdout y stderr se han redirigido a un solo archivo de destino.

Para que la salida de una transmisión se redirija y se elimine silenciosamente, dirija la salida a /dev/null .

Detección de redirección dentro de un script

Discutimos cómo un comando puede detectar si alguno de los flujos se está redirigiendo y puede elegir modificar su comportamiento en consecuencia. ¿Podemos lograr esto en nuestros propios guiones? Si podemos. Y es una técnica muy fácil de entender y emplear.

Anuncio publicitario

Escriba el siguiente texto en un editor y guárdelo como input.sh.

 #!/bin/bash

si [ -t 0 ]; entonces

  echo stdin procedente del teclado
 
demás

  echo stdin proveniente de una tubería o un archivo
 
fi

Use el siguiente comando para hacerlo ejecutable:

 chmod +x entrada.sh

La parte inteligente es la prueba entre corchetes. La opción -t (terminal) devuelve verdadero (0) si el archivo asociado con el descriptor de archivo termina en la ventana del terminal. Hemos usado el descriptor de archivo 0 como argumento para la prueba, que representa stdin .

Si stdin está conectado a una ventana de terminal, la prueba resultará verdadera. Si la stdin está conectada a un archivo o a una canalización, la prueba fallará.

Podemos usar cualquier archivo de texto conveniente para generar entradas para el script. Aquí estamos usando uno llamado dummy.txt.

 ./input.sh < ficticio.txt 

El resultado muestra que el script reconoce que la entrada no proviene de un teclado, sino de un archivo. Si lo desea, puede variar el comportamiento de su secuencia de comandos en consecuencia.

Anuncio publicitario

Eso fue con una redirección de archivos, intentémoslo con una tubería.

 muñeco de gato.txt | ./entrada.sh 

El script reconoce que su entrada se está canalizando hacia él. O más precisamente, reconoce una vez más que el flujo de stdin no está conectado a una ventana de terminal.

Ejecutemos el script sin canalizaciones ni redireccionamientos.

 ./entrada.sh 

El flujo de stdin está conectado a la ventana de la terminal y el script lo informa en consecuencia.

Para verificar lo mismo con el flujo de salida, necesitamos un nuevo script. Escriba lo siguiente en un editor y guárdelo como output.sh.

 #!/bin/bash

si [ -t 1 ]; entonces

echo stdout va a la ventana de terminal
 
demás

echo stdout está siendo redirigido o canalizado
 
fi

Use el siguiente comando para hacerlo ejecutable:

 chmod +x entrada.sh

El único cambio significativo en este script está en la prueba entre corchetes. Estamos usando el dígito 1 para representar el descriptor de archivo para stdout .

Probémoslo. Canalizaremos la salida a través de cat .

 ./salida | gato 

Anuncio publicitario

El script reconoce que su salida no va directamente a una ventana de terminal.

También podemos probar el script redirigiendo la salida a un archivo.

 ./salida.sh > capturar.txt 

No hay salida a la ventana del terminal, regresamos silenciosamente al símbolo del sistema. Como esperábamos.

Podemos mirar dentro del archivo capture.txt para ver qué se capturó. Use el siguiente comando para hacerlo.

 captura de gato.sh 

Nuevamente, la prueba simple en nuestro script detecta que el flujo de stdout no se envía directamente a una ventana de terminal.

Anuncio publicitario

Si ejecutamos el script sin conductos ni redirecciones, debería detectar que la stdout se envía directamente a la ventana de la terminal.

 ./salida.sh 

Y eso es exactamente lo que vemos.

corrientes de conciencia

Saber cómo saber si sus scripts están conectados a la ventana del terminal, a una tubería, o si están siendo redirigidos, le permite ajustar su comportamiento en consecuencia.

La salida de registro y diagnóstico puede ser más o menos detallada, dependiendo de si va a la pantalla oa un archivo. Los mensajes de error se pueden registrar en un archivo diferente al resultado normal del programa.

Como suele ser el caso, más conocimiento trae más opciones.

RELACIONADO: Las mejores computadoras portátiles Linux para desarrolladores y entusiastas