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.
Tabla de contenido
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, tienen dos extremos. Tienen una fuente y una salida. Cualquiera que sea el comando de Linux que esté utilizando, proporciona un extremo de cada secuencia. El otro extremo lo determina 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 flujo stdout (salida estándar). Los mensajes de error del comando se envían a través del flujo stderr (error estándar).
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 propio conducto para llevarlos a la ventana de la 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 proceso 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: salida estándar
2: stderr
Reacción a tuberías 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 hay más excepciones a esta regla que hay 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 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 si se redirige a un archivo? ¿Puede incluso saber si su entrada proviene del teclado o se está canalizando desde otro proceso?
En realidad, un proceso lo 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.
Podemos ver este cambio de comportamiento con mucha facilidad. Prueba estos dos comandos:
ls
ls | cat
El comando ls se comporta de manera diferente si su salida (stdout) se canaliza a otro comando. Es 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 se redirige:
ls > capture.txt
Redirigir stdout y stderr
Existe la ventaja de tener mensajes de error entregados por una transmisión dedicada. Significa que podemos redirigir la salida de un comando (stdout) a un archivo y seguir viendo los mensajes 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 ha redirigido stdout.
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 del flujo 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 > capture.txt
La salida de stdin se redirigió al archivo como se esperaba.
El símbolo de redirección> funciona con stdout por defecto. Puede utilizar uno de los descriptores de archivos 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 a stderr, use esta instrucción de redirección:
2>
Intentemos nuestra prueba nuevamente, y esta vez usaremos 2>:
./error.sh 2> capture.txt
El mensaje de error se redirige y el mensaje de eco de stdout se envía a la ventana de terminal:
El mensaje stderr está en capture.txt como se esperaba.
Redirigiendo tanto stdout como stderr
Seguramente, si podemos redirigir stdout o stderr a un archivo independientemente uno del otro, ¿deberíamos poder redirigirlos a 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
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 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 script error.sh.
> capture.txt: Redirige la secuencia de stdout al archivo capture.txt. > es la abreviatura de 1>.
2> & 1: Utiliza la instrucción de redireccionamiento &>. 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 redirige el flujo 1, stdout».
Revisemos el archivo capture.txt y veamos qué contiene.
cat capture.txt
Tanto las secuencias stdout como stderr se han redirigido a un único archivo de destino.
Para redirigir la salida de un flujo y desecharla 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 elegir alterar 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.
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. La opción -t (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 resultará verdadera. 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.shThe output shows that the script recognizes that the input isn’t coming from a keyboard, it is coming from a file. If you chose to, you could vary your script’s behavior accordingly.
Eso fue con una redirección de archivos, intentémoslo con una tubería.
cat dummy.txt | ./input.shEl guión reconoce que su entrada se canaliza a él. O más precisamente, reconoce una vez más que el flujo stdin no está conectado a una ventana de terminal.
Ejecutemos el script sin canalizaciones ni redireccionamientos.
./input.shLa secuencia stdin está conectada a la ventana de la terminal y el script lo informa en consecuencia.
Para comprobar 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 fiUtilice el siguiente comando para hacerlo ejecutable:
chmod +x input.shEl ú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.
./output | catEl script reconoce que su salida no va directamente a una ventana de terminal.
También podemos probar el script redireccionando la salida a un archivo.
./output.sh > capture.txtNo hay salida en la ventana del terminal, se nos devuelve silenciosamente al símbolo del sistema. Como era de esperar.
Podemos mirar dentro del archivo capture.txt para ver qué se capturó. Utilice el siguiente comando para hacerlo.
cat capture.shNuevamente, la prueba simple en nuestro script detecta que el flujo de salida estándar no se envía directamente a una ventana de terminal.
Si ejecutamos el script sin canalizaciones ni redirecciones, debería detectar que stdout se envía directamente a la ventana de la terminal.
./output.shY 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 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 de la salida normal del programa.
Como suele ser el caso, más conocimiento trae más opciones.