Los comandos de Linux set
y pipefail
dictan lo que sucede cuando ocurre una falla en un script de Bash . Hay más en qué pensar que si debe detenerse o continuar.
Los scripts de Bash Shell son geniales. Son rápidos de escribir y no necesitan compilación. Cualquier acción repetitiva o de varias etapas que necesite realizar puede incluirse 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 de 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 secuencia de comandos continuará procesando. Tal vez eso no es lo que querías. Si se produce un error al principio de la ejecución de la secuencia de comandos, podría generar problemas peores si se permite que se ejecute el resto de la secuencia de comandos.
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 canalización, no el del medio que falló. Por supuesto, también pueden ocurrir errores dentro de su secuencia de comandos, como intentar acceder a una variable no inicializada .
Los comandos set
y pipefile
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.
Aquí se explica cómo usarlos.
Aquí hay un script Bash trivial. Hace eco de dos líneas de texto en la terminal. Puede ejecutar este script si copia el texto en un editor y lo guarda como «script-1.sh».
#!/bin/bash echo Esto sucederá primero echo Esto sucederá segundo
Para hacerlo ejecutable necesitarás usarchmod
:
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 un poco el script. Le pediremos ls
que enumere los detalles de un archivo que no existe. Esto fallará. Guardamos esto como «script-2.sh» y lo hicimos ejecutable.
#!/bin/bash echo Esto sucederá primero ls nombre de archivo imaginario echo Esto sucederá segundo
Cuando ejecutamos este script, vemos el mensaje de error de ls
.
./script-2.sh
Aunque el ls
comando 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 la $?
variable que contiene el último código de retorno enviado al shell.
eco $?
El cero que se informa es el código de retorno del segundo eco en el script. Así que hay dos problemas con este escenario. La primera es que el script tuvo un error pero siguió 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 comprobar el éxito o el fracaso de este script, obtendrá una lectura falsa.
La set -e
opción (salir) hace que una secuencia de comandos se cierre si alguno de los procesos a los que llama genera un código de retorno distinto de cero. Todo lo que no sea cero se considera un fracaso.
Al agregar la set -e
opción al inicio del script, podemos cambiar su comportamiento. Esto es «script-3.sh».
#!/bin/bash conjunto -e echo Esto sucederá primero ls nombre de archivo imaginario echo Esto sucederá segundo
Si ejecutamos este script, veremos el efecto de set -e
.
./script-3.sh
eco $?
El script se detiene y el código de retorno enviado al shell es un valor distinto de cero.
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 seguirá procesándose.
Podemos ver los efectos de los comandos de canalización con diferentes códigos de retorno utilizando los integrados true
y false
shell. Estos dos comandos no hacen más que generar un código de retorno de cero o uno, respectivamente.
verdadero
eco $?
falso
eco $?
Si nos conectamos false
a true
—con false
la representación de un proceso fallido— obtenemos true
el código de retorno de cero.
falso | verdadero
eco $?
Bash tiene una variable de matriz llamada PIPESTATUS
, y captura todos los códigos de retorno de cada programa en la cadena de tuberías.
falso | cierto | falso | verdadero
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"
PIPESTATUS
solo retiene los códigos de retorno hasta que se ejecuta el siguiente programa, y tratar de determinar qué código de retorno va con qué programa puede volverse 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 conjunto -e echo Esto sucederá primero gato script-99.sh | wc-l echo Esto sucederá segundo
Esto falla, como era de esperar.
./script-4.sh
eco $?
El primer cero es la salida de wc
, que nos dice que no leyó ninguna línea del archivo que falta. El segundo cero es el código de retorno del segundo echo
comando.
Agregaremos -o pipefail
el archivo , lo guardaremos como «script-5.sh» y lo haremos ejecutable.
#!/bin/bash establecer -eo pipefail echo Esto sucederá primero gato script-99.sh | wc-l echo Esto sucederá segundo
Ejecutemos eso y verifiquemos el código de retorno.
./script-5.sh
eco $?
El script se detiene y el segundo echo
comando no se ejecuta. El código de retorno enviado al shell es uno, lo que indica correctamente un error.
Las variables no inicializadas pueden ser difíciles de detectar en un script del mundo real. Si intentamos con echo
el valor de una variable no inicializada, echo
simplemente imprime una línea en blanco. No lanza un mensaje de error. El resto del script seguirá ejecutándose.
Este es script-6.sh.
#!/bin/bash establecer -eo pipefail echo "$no establecido" echo "Otro comando de eco"
Lo ejecutaremos y observaremos su comportamiento.
./script-6.sh
eco $?
El script pasa por encima de la variable no inicializada y continúa ejecutándose. El código de retorno es cero. Tratar de encontrar un error como este en un script muy largo y complicado puede ser muy difícil.
Podemos atrapar este tipo de error usando la set -u
opción (desarmado). 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 lo haremos ejecutable.
#!/bin/bash establecer -eou fallo de tubería echo "$no establecido" echo "Otro comando de eco"
Ejecutemos el script:
./script-7.sh
eco $?
Se detecta la variable no inicializada, el script se detiene y el código de retorno se establece en uno.
La -u
opción (no establecida) es lo suficientemente inteligente como para no ser activada por situaciones en las que puede interactuar legítimamente con una variable no inicializada.
En “script-8.sh”, el script verifica si la variable New_Var
está inicializada o no. No desea que el guión se detenga aquí, en un guión del mundo real realizará más procesamiento y se ocupará de la situación usted mismo.
Tenga en cuenta que hemos agregado la -u
opción como la segunda opción en la declaración de conjunto. La -o pipefail
opción debe ser la última.
#!/bin/bash establecer -euo pipefail if [ -z "${Nueva_Var:-}" ]; entonces echo "New_Var no tiene ningún valor asignado". fi
En «script-9.sh», se prueba la variable no inicializada y, si no lo está, se proporciona un valor predeterminado en su lugar.
#!/bin/bash establecer -euo pipefail valor_predeterminado=484 Valor=${Nueva_Var:-$valor_predeterminado} echo "Nueva_Var=$Valor"
Los scripts pueden ejecutarse hasta su finalización.
./script-8.sh
./script-9.sh
Otra opción útil para usar es la opción set -x
(ejecutar e imprimir). Cuando estás escribiendo guiones, esto puede ser un salvavidas. imprime los comandos y sus parámetros a medida que se ejecutan.
Le brinda una forma rápida de seguimiento de ejecución «aproximada y lista». 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», la guardaremos como «script-10.sh» y la haremos ejecutable.
#!/bin/bash conjunto -euxo pipefail if [ -z "${Nueva_Var:-}" ]; entonces echo "New_Var no tiene ningún valor asignado". fi
Ejecútelo para ver las líneas de seguimiento.
./script-10.sh
Detectar errores en estos scripts de ejemplo triviales es fácil. Cuando comience a escribir guiones más complicados, estas opciones demostrarán su valor.
El mundo del gaming ha experimentado un crecimiento exponencial en los últimos años. La…
Stokkete/Shutterstock.com ¿Sigue utilizando una unidad flash USB obsoleta para almacenar sus archivos? ¿Por qué no…
LG Los fabricantes siempre intentan mejorar el rendimiento de imagen de los monitores. Como resultado,…
Patty Chan/Shutterstock.com Si cree en lo que ve en las redes sociales, puede pensar en…
Seksan.TH/Shutterstock.com Los servicios de suscripción como Netflix, Game Pass y Spotify nos permiten consumir tantas…
fatmawati achmad zaenuri/Shutterstock El acceso a Internet, oa cualquier otra red, se rige por la…