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

Contenidos

Ventana de terminal en una computadora con Linux

stdin, stdout, y stderr son tres flujos de datos que se crean al iniciar un comando de Linux. Puede usarlos para saber si sus scripts se están canalizando o redirigiendo. Te mostramos cómo.

Las corrientes se unen a dos puntos

Tan pronto como empiece a aprender sobre Linux y sistemas operativos similares a Unix, encontrará los términos stdin, stdout, y stederr. Estos son tres corrientes 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.

Las corrientes de datos, como las corrientes de agua, disponen dos extremos. Disponen una fuente y una salida. Cualquiera que sea el comando de Linux que esté usando, proporciona un extremo de cada secuencia. El otro extremo está determinado por el shell que lanzó el comando. Ese extremo se conectará a la ventana de la terminal, se conectará a una tubería o se redirigirá a un archivo u otro comando, de acuerdo con la línea de comando que lanzó el comando.

Las transmisiones estándar de Linux

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

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

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 involucran un flujo de datos. Entonces, el concepto de manejar un flujo de datos como un archivo no es tan exagerado.

A cada archivo asociado con un procedimiento se le asigna un número único para identificarlo. Esto se conoce como descriptor de archivo. Siempre que se requiera 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: stdin
  • 1: stdout
  • 2: stderr

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. A modo de 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 hay más excepciones a esta regla que hay casos que la obedecen.

En una línea semejante, cuando se habla de stdin, stdout, y stderr Es conveniente sacar a la luz el axioma aceptado de que un procedimiento ni sabe ni le importa dónde terminan sus tres corrientes estándar. ¿Debería importarle a un procedimiento si su salida va a la terminal o si se redirige a un archivo? ¿Puede inclusive saber si su entrada proviene del teclado o se está canalizando a él desde otro procedimiento?

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

Podemos ver este cambio de comportamiento con mucha facilidad. Prueba estos dos comandos:

ls

ls | cat

los ls El comando se comporta de manera distinto si su salida (stdout) se canaliza a otro comando. Está ls que cambia a una salida de una sola columna, no es una conversión realizada por cat. Y ls hace lo mismo si su salida está siendo redirigida:

ls > capture.txt

cat capture.txt

Redirigir stdout y stderr

Existe la ventaja de que los mensajes de error se envíen a través de una transmisión dedicada. Significa que podemos redirigir la salida de un comando (stdout) a un archivo y seguir viendo mensajes de error (stderr) en la ventana de la terminal. Puede reaccionar a los errores si es necesario, a medida que ocurren. Al mismo tiempo evita que los mensajes de error contaminen el archivo que stdout ha sido redirigido a.

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

#!/bin/bash

echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

Haga que el script sea ejecutable con este comando:

chmod +x error.sh

La primera línea del script hace eco del texto en la ventana de la terminal, a través de la stdout Arroyo. La segunda línea intenta tener acceso 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 ambas corrientes de salida, stdout y stderr, se han mostrado en las ventanas de la terminal.

Intentemos redirigir la salida a un archivo:

./error.sh > capture.txt

El mensaje de error que se envía a través de stderr aún se envía a la ventana de la terminal. Podemos chequear el contenido del archivo para ver si el stdout la salida fue al archivo.

cat capture.txt

La salida de stdin fue redirigido al archivo como se esperaba.

los > el símbolo de redirección funciona con stdout por defecto. 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 de nuevo nuestra prueba, y esta vez usaremos 2>:

./error.sh 2> capture.txt

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

Veamos qué hay en el archivo capture.txt.

cat capture.txt

los stderr el mensaje está en capture.txt como se esperaba.

Redirigiendo tanto stdout como stderr

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

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

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

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

Revisemos el contenido de cada archivo:

cat capture.txt
cat error.txt

Redirigir stdout y stderr al mismo archivo

Eso es genial, 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 ambos stdout y stderr al mismo archivo.

Podemos lograr esto con el siguiente comando:

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

Analicemos eso.

  • ./error.sh: Inicia el archivo de secuencia de comandos error.sh.
  • > capture.txt: Redirige el stdout transmitir al archivo capture.txt. > es una abreviatura de 1>.
  • 2> y 1: Utiliza la instrucción de redireccionamiento &>. Esta instrucción le posibilita decirle al shell que haga que un flujo llegue al mismo destino que otro flujo. En esta circunstancia, estamos diciendo «redireccionar flujo 2, stderr, al mismo destino que el flujo 1, stdout, está siendo redirigido a «.

No hay salida visible. Eso es alentador.

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

cat capture.txt

Ambos stdout y stderr las secuencias se han redirigido a un único archivo de destino.

Para que la salida de una secuencia se redirija y se deseche silenciosamente, dirija la salida a /dev/null.

Detección de redireccionamiento dentro de un script

Discutimos cómo un comando puede detectar si alguna de las transmisiones está siendo redirigida y puede seleccionar por modificar su comportamiento en consecuencia. ¿Podemos lograr esto en nuestros propios guiones? Si podemos. Y es una técnica muy fácil de comprender y emplear.

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

#!/bin/bash

if [ -t 0 ]; then

  echo stdin coming from keyboard
 
else

  echo stdin coming from a pipe or a file
 
fi

Utilice el siguiente comando para hacerlo ejecutable:

chmod +x input.sh

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

Si stdin está conectado a una ventana de terminal, la prueba será cierta. Si stdin está conectado a un archivo o tubería, 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 < dummy.txt

La salida 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.

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

cat dummy.txt | ./input.sh

El script reconoce que su entrada se está canalizando. O más exactamente, reconoce una vez más que el stdin stream no está conectado a una ventana de terminal.

Ejecutemos el script sin canalizaciones ni redireccionamientos.

./input.sh

los stdin stream está conectado a la ventana de terminal, y el script informa esto en consecuencia.

Para chequear 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

if [ -t 1 ]; then

echo stdout is going to the terminal window
 
else

echo stdout is being redirected or piped
 
fi

Utilice el siguiente comando para hacerlo ejecutable:

chmod +x input.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. Conduciremos la salida a través de cat.

./output | cat

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

Al mismo tiempo podemos probar el script redirigiendo la salida a un archivo.

./output.sh > capture.txt

No hay salida en la ventana del terminal, se nos devuelve silenciosamente al símbolo del sistema. Como podíamos esperar.

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

cat capture.sh

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

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

./output.sh

Y eso es exactamente lo que vemos.

Corrientes de conciencia

Saber cómo saber si sus scripts están conectados a la ventana de la terminal, o una tubería, o si están siendo redirigidos, le posibilita 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 distinto al de la salida normal del programa.

Como suele ser el caso, un mayor conocimiento aporta más opciones.

setTimeout(function(){
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version=’2.0′;
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s) } (window, document,’script’,
‘https://connect.facebook.net/en_US/fbevents.js’);
fbq(‘init’, ‘335401813750447’);
fbq(‘track’, ‘PageView’);
},3000);

Suscribite a nuestro Newsletter

No te enviaremos correo SPAM. Lo odiamos tanto como tú.