Shell Scripting: entrada, salida y error estándar

Al trabajar en aplicaciones de Linux, tenemos varias formas de obtener información del exterior y ponerla dentro: argumentos de línea de comando, variables de entorno, archivos. Todas estas fuentes son legales y buenas. Pero tiene un tamaño finito. Otra forma de establecer la comunicación son los flujos estándar: flujo de entrada ( stdin ) utilizado para obtener datos desde fuera de la aplicación, flujo de salida ( stdout ) para poner datos fuera de la aplicación y error para poner datos fuera de la aplicación ( stderr ).

flujo de aplicación estándar de Linux en sh

Cada flujo actúa como una tubería: tiene el mismo búfer para escribir y leer los datos. Este búfer está disponible para leer desde una aplicación y disponible para escribir desde otra. Al leer, el tamaño del búfer ocupado se reducirá y aumentará al escribir. Si la tasa promedio de lectura y escritura es igual, entonces los datos que pasan por el flujo pueden tener cualquier número de bytes de longitud.

Flujos de entrada/salida que operan en el ejemplo

Veamos un ejemplo de la aplicación «grep» que describe cómo interactúa con ella. 

cuerpo del guión:

#!/usr/bin/env bash
echo pattern | grep pattern
echo pattern | grep pattern

El script que se ejecuta en la consola:

cuerpo del script en el marco amarillo, salida a continuación

Esta vez ejecutamos 2 comandos: “cat stdio1.sh” – para listar el cuerpo del script, “./stdio1.sh” para ejecutar el script. El “ patrón de eco ” forma el flujo de salida estándar que está conectado al flujo de entrada estándar de grep . Entonces todos los datos llegan a grep. grep es una aplicación que escribe desde el flujo de entrada al flujo de salida si coincide con el patrón. La primera entrada no coincide; no se espera ningún resultado. La segunda string del script “patrón de eco | grep pattern” tiene la entrada adecuada: se ha pasado a la salida grep y se muestra en la consola a continuación.

Flujo de error operando en el ejemplo

Stderr es muy similar a stdout: con solo una diferencia: contendrá un informe de error si ocupa un lugar

cuerpo del guión:

#!/usr/bin/env bash

ls > /tmp/log
cat /tmp/log

ls /not/existed_path > /tmp/log
cat /tmp/log
cat /tmp/log

rm /tmp/log

El script que se ejecuta en la consola:

cuerpo del script en el marco amarillo, salida a continuación

En este script, hacemos una lista de archivos en el directorio actual («ls») y redirigimos la salida estándar al archivo («/tmp/log»). Luego, mostramos los datos de este archivo en la consola desde el flujo de salida estándar de la utilidad cat que lee el archivo. A continuación, intentamos enumerar los archivos en la carpeta que no existe y almacenar los resultados en el archivo como se indicó anteriormente, y mostrarlo dos veces. Pero no hay efecto. Solo una salida sobre el error en la consola. Esto se debe a que este error proviene del flujo de errores estándar de ls. Eliminamos el archivo para liberar algo de espacio “ /tmp/log ”.

Redirección de flujos

Es posible manipular los flujos estándar: redirigirlos o usar tuberías para procesarlos.

cuerpo del guión:

#!/usr/bin/env bash

ls /not/existed_path 2>/dev/null
ls * /not/existed_path > /tmp/log 2> /tmp/err_log
cat /tmp/log
rm /tmp/log /tmp/err_log

El script que se ejecuta en la consola:

cuerpo del script en el marco amarillo, salida a continuación

Usamos la acción de redirección » > » en este comando. /dev/null : es un archivo de terminación de transmisión para descartar cualquier entrada sin procesamiento. La cláusula » 2> » redirige el flujo de salida estándar al archivo. Ahora es posible ver la salida y los errores más tarde llamando a «cat /tmp/log» o «cat /tmp/err_log».

Descartar la salida

En algunos casos, es útil descartar toda la salida de la aplicación (para ahorrar espacio de almacenamiento o eliminar las fuentes de datos sin importancia para analizar). Debemos recordar que debemos silenciar no solo el flujo de salida estándar, sino también el flujo de error estándar . Veamos un ejemplo de cómo funciona.

cuerpo del guión:

#!/usr/bin/env bash

ls . unexisted_file > /dev/null
ls . unexisted_file > /dev/null 2>&1

El script que se ejecuta en la consola:

 cuerpo del script en el marco amarillo, salida a continuación

En ambas líneas del script , el flujo de salida estándar se redirige al archivo /dev/null . Este archivo no es un archivo en sí mismo: sino un dispositivo Linux especial con una interfaz de archivo. Tiene una función de escritura disponible desde shell (que no hace nada). Entonces toda la entrada simplemente se descarta. Pero la segunda string del script tiene una diferencia con la primera: “ 2>&1 ” al final del comando. Estos símbolos indican que el segundo flujo estándar ( flujo de error estándar ) debe dirigirse al primer flujo estándar (flujo de salida estándar ) de forma permanente para este comando. Es por eso que solo vemos un mensaje de error en la consola: en la segunda string de comando del script.flujo de error estándar redirigido al dispositivo de archivo de terminación /dev/null al final.

Corrientes canalizadas

También puede ser útil para modificar la transmisión. es capaz de ejecutar varias aplicaciones conectadas por las corrientes. 

cuerpo del guión:

#!/usr/bin/env bash

touch /tmp/a
ls /tmp/* 2> /dev/null | grep -w a
rm /tmp/a

El script que se ejecuta en la consola:

cuerpo del script en el marco amarillo, salida a continuación

Aquí recopilamos la lista y establecemos el flujo de salida estándar » ls » como flujo de entrada estándar grep usando » | ”. En “ 2>, el flujo de errores estándar se redirige al archivo de terminación. El flujo de salida de grep contiene el nombre de archivo » /tmp/a » de la lista que coincide con el patrón grep. 

Aquí documento

Aquí, el documento es una opción de redirección para completar el flujo de entrada de la aplicación de forma nativa:

application << delimiter
some useful text
delimiter

cuerpo del guión:

#!/usr/bin/env bash

grep perfect << EOF
    PERFECT STORY
    past perfect
    is it Perfect?
EOF

El script que se ejecuta en la consola.

cuerpo del script en el marco amarillo, salida a continuación

Como podemos ver, solo la segunda string de 3 de las strings de texto para el flujo de entrada estándar grep delimitado por «EOF» coincide con el patrón grep : es por eso que pasó al flujo de salida estándar grep y se muestra en la consola a continuación.

Conclusión    

Existen varias utilidades estándar para trabajar con flujos ( cat , cut , grep , sed , tr , …). Puede usarlo o escribir uno propio para crear una canalización de procesamiento de flujo de datos que se ajuste a sus necesidades. Bajo el capó, funcionará con stdin , stdout , stderr .

Publicación traducida automáticamente

Artículo escrito por chashchegorov y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

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