Todo sobre Apple, Android, Juegos Apks y Sitios de Peliculas

Cómo utilizar set y pipefail en Bash Scripts en Linux

el linux

 set 

y los comandos pipefail dictan lo que sucede cuando ocurre una falla en un script Bash. Hay más en qué pensar que si debería detenerse o continuar.

Relacionado: La guía para principiantes sobre secuencias de comandos de Shell: conceptos básicos

Scripts de Bash y condiciones de error

Los scripts de Bash Shell son geniales. Son rápidos de escribir y no necesitan ser compilados. Cualquier acción repetitiva o de varias etapas que necesite realizar se puede incluir en un guión conveniente. Y debido a que los scripts pueden llamar a cualquiera de las utilidades estándar de Linux, no está limitado a las capacidades del propio lenguaje shell.

Pero pueden surgir problemas cuando llama a una utilidad o programa externo. Si falla, la utilidad externa se cerrará y enviará un código de retorno al shell, e incluso podría imprimir un mensaje de error en la terminal. Pero su guión seguirá procesándose. Quizás eso no sea lo que querías. Si se produce un error al principio de la ejecución del script, podría provocar problemas peores si se permite ejecutar el resto del script.

Relacionado: ¿Qué es Bash Shell y por qué es tan importante para Linux?

Puede verificar el código de retorno de cada proceso externo a medida que se completan, pero eso se vuelve difícil cuando los procesos se canalizan a otros procesos. El código de retorno será del proceso al final de la tubería, no del proceso en el medio que falló. Por supuesto, también pueden ocurrir errores dentro de su script, como intentar acceder a una variable no inicializada.

El

 set 

y

 pipefile 

Los comandos le permiten decidir qué sucede cuando ocurren errores como estos. También le permiten detectar errores incluso cuando ocurren en medio de una cadena de tuberías.

A continuación se explica cómo utilizarlos.

Demostrando el problema

Aquí hay un script Bash trivial. Hace eco de dos líneas de texto al terminal. Puede ejecutar este script si copia el texto en un editor y lo guarda como “script-1.sh.”

#!/bin/bash

echo This will happen first

echo This will happen second

Para hacerlo ejecutable necesitarás usar chmod:

chmod +x script-1.sh

Deberá ejecutar ese comando en cada script si desea ejecutarlos en su computadora. Ejecutemos el script:

./script-1.sh

Las dos líneas de texto se envían a la ventana del terminal como se esperaba.

Modifiquemos ligeramente el guión. Le pediremos a ls que enumere los detalles de un archivo que no existe. Esto fracasará. Guardamos esto como “script-2.sh” y lo hizo ejecutable.

#!/bin/bash

echo This will happen first

ls imaginary-filename

echo This will happen second

Cuando ejecutamos este script vemos el mensaje de error de ls.

./script-2.sh

Aunque el comando ls falló, el script continuó ejecutándose. Y aunque hubo un error durante la ejecución del script, el código de retorno del script al shell es cero, lo que indica éxito. Podemos verificar esto usando echo y $? variable que contiene el último código de retorno enviado al shell.

echo $?

El cero que se informa es el código de retorno del segundo eco del script. Entonces hay dos problemas con este escenario. La primera es que el script tuvo un error pero continuó ejecutándose. Eso puede generar otros problemas si el resto del script espera o depende de que la acción que falló realmente tuvo éxito. Y la segunda es que si otro script o proceso necesita verificar el éxito o el fracaso de este script, obtendrá una lectura falsa.

La opción set -e

La opción set -e (salir) hace que un script salga si alguno de los procesos que llama genera un código de retorno distinto de cero. Cualquier valor distinto de cero se considera un fracaso.

Al agregar la opción set -e al inicio del script, podemos cambiar su comportamiento. Esto es “guion-3.sh.”

#!/bin/bash 

set -e

echo This will happen first

ls imaginary-filename

echo This will happen second

Si ejecutamos este script veremos el efecto de set -e.

./script-3.sh
echo $?

El script se detiene y el código de retorno enviado al shell es un valor distinto de cero.

Cómo lidiar con fallas en las tuberías

Las tuberías añaden más complejidad al problema. El código de retorno que sale de una secuencia canalizada de comandos es el código de retorno del último comando de la cadena. Si hay una falla con un comando en el medio de la cadena, volvemos al punto de partida. Ese código de retorno se pierde y el script continuará procesándose.

Podemos ver los efectos de los comandos de canalización con diferentes códigos de retorno utilizando las funciones integradas de shell verdadero y falso. Estos dos comandos no hacen más que generar un código de retorno de cero o uno, respectivamente.

true
echo $?
false
echo $?

Si canalizamos falso a verdadero (donde falso representa un proceso fallido), obtenemos el código de retorno de verdadero cero.

false | true
echo $?

Bash tiene una variable de matriz llamada PIPESTATUS, que captura todos los códigos de retorno de cada programa en la cadena de tuberías.

false | true | false | true
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"

PIPESTATUS sólo retiene los códigos de retorno hasta que se ejecuta el siguiente programa, y ​​tratar de determinar qué código de retorno va con cada programa puede resultar muy complicado muy rápidamente.

Aquí es donde entran set -o (opciones) y pipefail. Esto es “script-4.sh.” Esto intentará canalizar el contenido de un archivo que no existe en wc.

#!/bin/bash 

set -e

echo This will happen first

cat script-99.sh | wc -l

echo This will happen second

Esto falla, como era de esperar.

./script-4.sh
echo $?

El primer cero es la salida de wc, que nos indica que no leyó ninguna línea del archivo faltante. El segundo cero es el código de retorno del segundo comando de eco.

Agregaremos el -o pipefail, lo guardaremos como “script-5.sh”, y hacerlo ejecutable.

#!/bin/bash 

set -eo pipefail

echo This will happen first

cat script-99.sh | wc -l

echo This will happen second

Ejecutemos eso y verifiquemos el código de retorno.

./script-5.sh
echo $?

El script se detiene y el segundo comando echo no se ejecuta. El código de retorno enviado al shell es uno, lo que indica correctamente una falla.

Relacionado: Cómo utilizar el comando Echo en Linux

Captura de variables no inicializadas

Las variables no inicializadas pueden ser difíciles de detectar en un script del mundo real. Si intentamos repetir el valor de una variable no inicializada, echo simplemente imprime una línea en blanco. No genera un mensaje de error. El resto del script continuará ejecutándose.

Esto es guión-6.sh.

#!/bin/bash 

set -eo pipefail

echo "$notset"

echo "Another echo command"

Lo ejecutaremos y observaremos su comportamiento.

./script-6.sh
echo $?

El script pasa por encima de la variable no inicializada y continúa ejecutándose. El código de retorno es cero. Intentar encontrar un error como este en un script muy largo y complicado puede resultar muy difícil.

Relacionado: Cómo trabajar con variables en Bash

Podemos detectar este tipo de error usando la opción set -u (desarmar). Lo agregaremos a nuestra creciente colección de opciones de configuración en la parte superior del script, lo guardaremos como “script-7.sh”, y hacerlo ejecutable.

#!/bin/bash 

set -eou pipefail

echo "$notset"

echo "Another echo command"

Ejecutemos el script:

./script-7.sh
echo $?

Se detecta la variable no inicializada, el script se detiene y el código de retorno se establece en uno.

La opción -u (desarmar) es lo suficientemente inteligente como para no activarse en situaciones en las que puede interactuar legítimamente con una variable no inicializada.

En “guión-8.sh”, el script comprueba si la variable New_Var está inicializada o no. No desea que el script se detenga aquí; en un script del mundo real, realizará un procesamiento adicional y se ocupará de la situación usted mismo.

Note que hemos agregado la opción -u como segunda opción en la declaración set. La opción -o pipefail debe aparecer al final.

#!/bin/bash 

set -euo pipefail

if [ -z "${New_Var:-}" ]; then

echo "New_Var has no value assigned to it."

fi

En “guión-9.sh”, se prueba la variable no inicializada y, si no está inicializada, se proporciona un valor predeterminado en su lugar.

#!/bin/bash

set -euo pipefail

default_value=484

Value=${New_Var:-$default_value}

echo "New_Var=$Value"

Se permite que los guiones se ejecuten hasta su finalización.

./script-8.sh
./script-9.sh

Sellado con hacha

Otra opción útil es la opción set -x (ejecutar e imprimir). Cuando escribes guiones, esto puede salvarte la vida. imprime los comandos y sus parámetros a medida que se ejecutan.

Le brinda una forma rápida y “aproximada” de seguimiento de ejecución. Aislar fallas lógicas y detectar errores se vuelve mucho, mucho más fácil.

Agregaremos la opción set -x a “script-8.sh”, guárdelo como “script-10.sh” y hágalo ejecutable.

#!/bin/bash

set -euxo pipefail

if [ -z "${New_Var:-}" ]; then

echo "New_Var has no value assigned to it."

fi

Ejecútelo para ver las líneas de seguimiento.

./script-10.sh

Detectar errores en estos triviales scripts de ejemplo es fácil. Cuando empiece a escribir guiones más complicados, estas opciones demostrarán su valía.

Resumen del Contenido