Ventana de terminal en una computadora con Linux

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

Fatmawati Achmad Zaenuri / Shutterstock.com

stdin, stdout, y stderr son tres flujos de datos que se crean cuando emite un comando de Linux. Puede usarlos para averiguar si sus scripts son redirigidos o redirigidos. Te mostramos cómo.

Los flujos unen dos puntos

Tan pronto como empiece a familiarizarse con los sistemas operativos Linux y 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, estos 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 utilice, proporciona un extremo de cada flujo. El otro extremo lo determina el shell que emitió el comando. Este extremo se conectará a la ventana de la terminal, se conectará a una tubería o se redirigirá a un archivo u otro comando, según la línea de comando que inició el comando.

Flujos estándar de Linux

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

Entonces puede ver que hay dos flujos de salida, stdout y stderr, y un flujo de entrada, stdin. Dado que los mensajes de error y la salida normal tienen cada uno su propia ruta para enrutarlos a la ventana de la terminal, se pueden manejar de forma independiente entre sí.

Las transmisiones se tratan como archivos

Las transmisiones 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 administrar un flujo de datos como un archivo no es tan descabellado.

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

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

  • 0: stdin
  • 1: salida estándar
  • 2: stderr

Responder a canalizaciones y redireccionamientos

Para facilitar que alguien presente 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 de hecho, hay no hay más excepciones a esta regla que no hay casos que le obedezcan.

En la misma línea, hablando de stdin, stdout, y stderr Es conveniente repetir el axioma aceptado de que un proceso ni 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 siquiera saber si su entrada proviene del teclado o si algún otro proceso la enruta allí?

De hecho, un proceso lo sabe, o al menos puede averiguarlo, si elige verificarlo, y puede cambiar su comportamiento en consecuencia si el autor del software decide agregar esta funcionalidad.

Podemos ver fácilmente este cambio de comportamiento. Prueba estos dos comandos:

ls

ls | cat

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

ls > capture.txt

cat capture.txt

Redirección de stdout y stderr

Existe la ventaja de que los mensajes de error se envíen a través de una fuente dedicada. Esto significa que podemos redirigir la salida de un comando (stdout) en un archivo y siempre aparecen mensajes de error (stderr) en la ventana de la terminal. Puede reaccionar a los errores si es necesario, a medida que ocurren. También evita que los mensajes de error contaminen el archivo que stdout fue 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 devuelve el texto a la ventana de terminal, a través de la stdout flujo. 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 los dos flujos de salida, stdout y stderr, se mostraban en las ventanas de la terminal.

Intentemos redirigir la salida a un archivo:

./error.sh > capture.txt

El mensaje de error transmitido a través de stderr siempre se envía a la ventana de la terminal. Podemos comprobar 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 redireccionamiento funciona con stdout por defecto. Puede utilizar cualquiera de los descriptores de archivos digitales para indicar el flujo de salida estándar que desea redirigir.

Para redirigir explícitamente stdout, use esta declaración de redireccionamiento:

1>

Para redirigir explícitamente stderr, use esta declaración de redireccionamiento:

2>

Intentemos nuestra prueba de nuevo, 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.

Redirigir stdout y stderr

Seguro que si podemos redirigir a uno u otro stdout Dónde stderr a un archivo independientemente el uno del otro, ¿deberíamos poder redirigirlos a ambos al mismo tiempo, a dos archivos diferentes?

Sí, podemos. Este comando dirigirá stdout en un archivo llamado capture.txt y stderr en 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 salida visible en la ventana del terminal. Regresamos a la línea de comandos como si no hubiera pasado nada.

Revisemos el contenido de cada archivo:

cat capture.txt
cat error.txt

Redirigir stdout y stderr al mismo archivo

Eso es bueno, cada uno de nosotros tiene flujos de salida estándar 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 esto.

  • ./error.sh: inicia el archivo de script error.sh.
  • > capture.txt: redirigirlo stdout transmitir al archivo capture.txt. > es un atajo para 1>.
  • 2> & 1: utiliza la instrucción de redireccionamiento &>. Esta declaración le permite decirle al shell que haga que una corriente llegue al mismo destino que otra corriente. En este caso, decimos «redireccionar flujo 2, stderr, al mismo destino que el flujo 1, stdout, se redirige a.

No hay salida visible. Es alentador.

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

cat capture.txt

Los dos stdout y stderr las secuencias se redirigieron a un único archivo de destino.

Para que la salida de una transmisión se redireccione y se suprima silenciosamente, apunte la salida a /dev/null.

Detección de redireccionamiento en un script

Hemos explicado cómo un comando puede detectar si alguno de los flujos está redirigido y puede optar por modificar su comportamiento en consecuencia. ¿Podemos lograr esto en nuestros propios guiones? Sí, podemos. Y es una técnica muy fácil de entender y usar.

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 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. Usamos el descriptor de archivo 0 como argumento de la prueba, que representa stdin.

stdin está conectado a una ventana de terminal, la prueba resultará verdadera. sí stdin está conectado a un archivo o tubería, la prueba fallará.

Podemos usar cualquier archivo de texto conveniente para generar entradas en 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 cambiar el comportamiento de su secuencia de comandos en consecuencia.

Fue con la redirección de archivos, probemos con una tubería.

cat dummy.txt | ./input.sh

El script reconoce que su entrada se enruta allí. O más precisamente, 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 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

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. Usamos el número 1 para representar el descriptor de archivo para stdout.

Probémoslo. Dirigiremos la salida por cat.

./output | cat

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.

./output.sh > capture.txt

No hay salida en la ventana de terminal, se nos devuelve silenciosamente al símbolo del sistema. Como se podría 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 de nuestro script detecta que el stdout el flujo no se envía directamente a una ventana de terminal.

Si ejecutamos el script sin canales o redireccionamientos, debería detectar que stdout viene directamente a la ventana de la terminal.

./output.sh

Y eso es exactamente lo que estamos viendo.

Corrientes de conciencia

Saber cómo saber si sus scripts están conectados a la ventana de la 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 guardar en un archivo diferente al de la salida normal del programa.

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

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Experto Geek - Tu Guía en Tendencias Tecnológicas