Conceptos básicos de automatización de bash y secuencias de comandos (parte 3)

Contenidos

Shutterstock / Mopic

En este post final de nuestra serie de tres partes básicas de automatización y secuencias de comandos de Bash, exploraremos la depuración de secuencias de comandos, la ejecución de secuencias de comandos como un procedimiento en segundo plano y la importación de otras secuencias de comandos usando el comando de origen.

Conceptos básicos de automatización de bash y secuencias de comandos

Si desea comenzar por el principio, lea nuestro post Bash Automation and Scripting Basics Part 1. Este post final de nuestra serie de tres partes sobre la automatización de Bash y los conceptos básicos de la creación de scripts analizará la ejecución de scripts como un procedimiento en segundo plano.

Además queremos depurar rápidamente nuestros scripts con un mínimo de complicaciones y resultados de alta gama. Esto se puede hacer usando una función de rastreo muy útil, construida de forma directa en el intérprete de comandos de Bash. Veremos esto en el segundo tema. Además puede estar atento a nuestro próximo post sobre el shellcheck relacionado.

Y para terminar exploraremos cómo ejecutar scripts como un procedimiento en segundo plano. Aunque esto puede proporcionar beneficios inmediatos modestos, como iniciar varias tareas al mismo tiempo, además sienta algunas de las bases para posteriores scripts de subprocesos múltiples más avanzados.

Depuración de secuencias de comandos

¡La depuración de un script en Bash no tiene por qué ser difícil! Esté atento al portal web de CloudSavvyIT, puesto que pronto revisaremos la herramienta de depuración de shellcheck más completa para Bash, pero por el momento me agradaría presentarle una magnífica manera de depurar scripts de Shell de una manera sencilla y fácil de comprender.

Dentro del caparazón de Bash, que después de todo es un «sencillo» binario ejecutándose en su máquina, dicho de otra forma, el bash binario, se proporciona una opción (-x) que, según man bash (ejecutar esto en su terminal mostrará un manual de Bash) se describe como Imprimir comandos y sus argumentos a medida que se ejecutan¡Y esto es exactamente lo que hace! ¿Cómo ayudará esto con la depuración? Eche un vistazo al siguiente ejemplo:

#!/bin/bash

A=1
B=2
if [ "${AA}" == "1" -o "${B}" == "1" ]; then 
  echo "One ('1') was definitely stored in either the variable A, or the variable B"
  exit 0
else
  echo "Assert: could not locate the value '1' in the variables A and B"
  exit 1
fi

Un pequeño script de Bash con un error

Aquí comprobamos las variables A y B contra el valor 1. los -o modismo en el if declaración significa OR, dicho de otra forma, la primera parte (A, o mejor AA aquí está 1) es cierto, o la segunda parte (B es 1) es cierto y, en tal caso, se logra el éxito.

La salida del script será la aserción programada y el programa terminará con un código de salida de 1, lo que de forma general significa que hubo algún error. Si la secuencia de comandos hubiera funcionado correctamente, se mostraría un mensaje de confirmación y la secuencia de comandos terminaría con un código de salida de 0, lo que de forma general significa que hubo éxito en cualquier cosa que se pretendía hacer con el script o la utilidad.

Entonces, ¿por qué el script se ejecuta en la aserción? Puede que ya hayas notado que la variable A encontré un error tipográfico en nuestro if declaración, registrada en el código como AA: ¡un insecto! Podríamos ir y verificar el script, y si es tan corto y sencillo como el que se muestra aquí, el error se encontraría rápidamente. Pero para un programa de 5000 líneas, la respuesta no es tan simple, especialmente si utiliza múltiples subprocesos, subcapas complejas, etc.

Depuramos esto ahora con el -x opción a Bash. Tal vez recuerde de la segunda parte de nuestro curso de conceptos básicos de automatización y scripting de Bash que se puede iniciar un subshell usando un $( ... ) conjunto de modismos. Además se puede iniciar simplemente escribiendo bash, o para este caso bash -x dentro de nuestro caparazón superior. En esta circunstancia, ejecutaremos el script dentro de nuestro subshell Bash, con el -x opción para observar lo que sucede paso a paso.

Ejecutando nuestro script de smalls con bash -x

Así ejecutamos bash -x ./test_debugging.sh y observe que se está realizando la próxima verificación condicional: '[' '' == 1 -o 2 == 1 ']'. Notamos que algo anda mal: el valor de 2 está siendo comparado con 1 en la segunda parte de nuestra verificación condicional, pero ¿qué está sucediendo en la primera parte? Algo se está comparando con 1, pero eso alguna cosa está … vacío (como lo indica la cadena vacía '')!

Después revisamos nuestro script por qué ese lugar vacío está allí y por qué no se llenó con el valor de nuestro A variable. Rápidamente nos damos cuenta de la AA en lugar de A error, corrija el error y el script ahora funciona bien.

El script corregido con el error corregido.

Algo verdaderamente genial para recordar al utilizar bash -x es que tu puedes tee (lee esto como ‘Copiar’) la salida del comando Bash redirigiendo stderr (la salida de error) a stdout (la salida estándar) y capturando la misma con tee:

Usando tee en combinación con bash -x

Aquí estamos ejecutando nuestro script fijo y estamos redirigiendo la salida de error (bash -x envía toda su salida de depuración informativa a stderr, la salida de error estándar, y no a stdout) usando 2>&1 (que redirige nuestra salida stderr a stdout – nuestra salida estándar – en su lugar). Después capturamos stdout usando tee y esto guardará la salida en el archivo especificado, a saber bash_-x_output.txt.

Esto posibilita que un desarrollador de Bash revise lentamente, en un formato paso a paso, su código escrito. Especialmente cuando los programas se vuelven complejos, disponen funciones, se vuelven multiproceso, inician procesos en segundo plano, etc., esta forma de depuración puede ser muy valiosa. Como ejemplo, tiendo a utilizar bash -x aproximadamente una vez cada quince días para depurar scripts complejos.

Ejecución de scripts como procesos en segundo plano

Ejecutar un script como procedimiento en segundo plano es sencillo: simplemente agregue & al final del nombre del script (con un espacio entre ellos). Definimos background.sh como sigue:

#!/bin/bash

sleep 2

Después lo iniciamos de la próxima manera, para resaltar el hecho de que se está ejecutando en segundo plano:

Flujo de varios comandos Bash con uno de esos comandos como proceso en segundo plano

Lo que podemos ver que sucede aquí es como sigue: background.sh El script se inicia en segundo plano (dado el & adjunto al nombre del script con un espacio), e inmediatamente volverá el símbolo del sistema. Usamos esto aquí especificando el siguiente comando (sleep 1) de forma directa después del & idioma de fondo, que además termina ese comando un comando único / único (dicho de otra forma, sleep 1 es un comando absolutamente nuevo).

Además damos por terminada nuestra sleep 1 comando con un frecuente fin de mando Bash idiom, después de lo cual ejecutaremos un echo que el sleep 1 está completo / hecho. A continuación, veamos qué sucede en la ejecución de esta línea.

Inmediatamente, nuestro procedimiento / script en segundo plano (background.sh) se inicia y se ejecutará durante unos 2 segundos. El PID (identificador de procedimiento) del procedimiento en segundo plano iniciado se muestra visualmente (dicho de otra forma, 773183 para nuestro primer[1]) procedimiento en segundo plano, y este PID será distinto cada vez que inicie un programa / procedimiento en segundo plano), y nuestro sleep 1 (la próxima instrucción para la ejecución) ahora se puede ejecutar puesto que el otro programa ha devuelto nuestro mensaje (aún cuando no se muestra de forma directa aquí, esto es lo que ocurre cuando inicia un procedimiento en segundo plano; inmediatamente obtiene el símbolo del sistema de vuelta).

los sleep 1 comienza (con el sleep 2 o más exactamente el background.sh La secuencia de comandos aún se ejecuta en segundo plano, como un procedimiento distinto, en una subcapa iniciada bajo esta capa superior o de nivel superior) y termina después de 1 segundo. Después de esto nuestro echo se ejecuta, mostrándonos el sleep 1 Esta completo. Un segundo después, nuestro background.sh el procedimiento redondea su espera de 2 segundos y termina.

No vemos que haya terminado puesto que el shell Bash espera alguna interacción para mostrarnos mensajes de estado. Por eso, tan pronto como presionemos Intro, en cualquier momento después de que finalice la suspensión de dos segundos, veremos la terminación del procedimiento en segundo plano como una [1]+ Done ./background.sh mensaje de estado. Si vuelve a la segunda parte de nuestra miniserie, es factible que además vea cómo podríamos haber utilizado wait aquí para esperar la finalización / terminación del PID del procedimiento en segundo plano. Además destaca cuántos comandos y utilidades se pueden utilizar de forma combinatoria en Bash.

Importación de scripts usando fuente

La importación de otro script se puede hacer fácilmente usando Bash source mando. Considere el siguiente guión testsource.sh:

#!/bin/bash

source mysource.sh

echo "${MYVAR}"

Y el emparejamiento mysource.sh:

#!/bin/bash

MYVAR="Hello CloudSavvyIT Readers!"

Si simplemente hacemos el primer script (testsource.sh) ejecutable (usando chmod +x testsource.sh), pero no el segundo script (en realidad, desarmamos la bandera ejecutable para mostrar claramente que esto funciona usando chmod -x sobre mysource.sh), el segundo script se sigue llamando correctamente como consecuencia de la source comando, y se ejecuta como parte del testsource.sh texto:

Obtención de un script con el comando de origen Bash

En el mysource.sh script, establecemos la variable MYVAR para Hello CloudSavvyIT Readers!. Este script se obtiene posteriormente del testsource.sh script usando la instrucción source mysource.sh. Esto causará mysource.sh para ser ejecutado en ese punto el código, y cuando esté completo, el testsource.sh La secuencia de comandos continuará ejecutándose, aún cuando cualquier cosa establecida en el mysource.sh será retenido (piense en esto como procedente de otro guión para recordar el funcionamiento de este más fácilmente).

En resumen

Echamos un vistazo a la depuración de scripts usando bash -x para mostrar todos los comandos ejecutados. Además exploramos cómo ejecutar una secuencia de comandos como procedimiento en segundo plano y aprendimos cómo podemos importar secuencias de comandos usando el código fuente. Gracias por estar atentos a esta serie de 3 partes, ¡de la cual este fue el post final!

Si está interesado en obtener más información sobre Bash, ¿qué tal si consulte nuestros posts o Primer: Bash Loops: para, mientras y hasta, Pruebas condicionales en Bash: if, then, else, elif y Bash Funciones y variables locales

Suscribite a nuestro Newsletter

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