Tutoriales

Cómo evitar el infinito hasta que se bucle en el script bash usando tiempo de espera

¿Alguna vez ha escrito un script bash esperando que el servicio esté listo antes de continuar? Ese es un patrón común. Pero a veces, el servicio nunca estará en línea. Cuando esto sucede, sus scripts pueden atascarse en un bucle infinito que quizás ni siquiera se den cuenta.

Este artículo le mostrará cómo resolver este problema. Aprenderás usar timeout Comando en Bash Evite este problema.

Comencemos.

Simple until Un posible bucle que sale mal

Para fines de demostración, tomemos PostgreSQL como ejemplo.

Digamos que está escribiendo un script de implementación. Antes de ejecutar la migración de la base de datos, debe asegurarse de que se inicie PostgreSQL.

Podrías escribir:

until pg_isready -h 127.0.0.1 -p 5432; do
    echo "Waiting for database..."
    sleep 1
done

echo "Database is up! Running migrations..."
./run-migrations.sh

A primera vista, esto funciona. Sin embargo, si la base de datos nunca comienza (debido a errores tipográficos, bloqueos o mala configuración), su script esperará para siempre. Esto es arriesgado, especialmente en la automatización.

Decir hola timeout: Red de seguridad simple

Bash tiene una forma incorporada de verificar las cosas para siempre, pero no sabe cuándo rendirse. este timeout El comando solucionó esto. Si lleva demasiado tiempo, ejecuta el comando y lo mata.

Así es como funciona:

timeout 5s sleep 10

Comienza este comando sleep 10pero después de 5 segundos, timeout Envíe la señal y deténgala.

También puede verificar el código de salida después:

echo $?
  • 124 Lo que significa que se agotó.
  • 0 Lo que significa que se completa normalmente.

¿Por qué no se puede usar? timeout y until Directamente

En este punto, podrías intentar algo como esto:

timeout 30s until pg_isready -h 127.0.0.1 -p 5432; do
    sleep 1
done

Pero esto no funciona. ¿Por qué? porque until No es un pedido. Esta es una palabra clave BASH. timeout Use solo con comandos reales: comandos que se ejecutan en un proceso, p. sleep,,,,,,,,,,, para curlo ls.

La forma correcta de usar el tiempo de espera en Bash: envuélvalo en el proceso de bash

Para solucionar esto, debe envolver el bucle en un subproceso. Aquí está la forma correcta:

timeout 30s bash -c '
until pg_isready -h 127.0.0.1 -p 5432; do
    echo "Waiting for database..."
    sleep 1
done
'

Ahora el bucle se ejecuta en un nuevo proceso bash. timeout El proceso puede ser monitoreado y asesinado si es necesario.

verificar until y timeout En el carnaval

Así es como puede verificar el PostgreSQL anterior pg_isready Ejemplo en su sistema local.

Asegúrese de tener:

  • PostgreSQL instalado (pg_isready Llevar contigo).
  • Ejecutar un servidor PostgreSQL local o remoto (o intencionalmente no ejecutar para simular una falla).
  • Bash Shell (el valor predeterminado para la mayoría de los sistemas Linux/MacOS).

1. Confirmar pg_isready trabajar

correr:

pg_isready -h 127.0.0.1 -p 5432

Si PostgreSQL se está ejecutandola salida será:

127.0.0.1:5432 - accepting connections
Confirmar PG_ISReady funciona

2. Detente PostgreSQL para simular fallido

Si está utilizando Systemd:

sudo systemctl stop postgresql

Luego corre:

pg_isready -h 127.0.0.1 -p 5432

Obtendrá la siguiente salida:

127.0.0.1:5432 - no response
Detener PostgreSQL y verifique si PG_ISREWY es válido
Detener PostgreSQL y verifique si PG_ISREWY es válido

3. Prueba until El bucle no tiene tiempo de espera

Ejecute el siguiente código en su terminal:

until pg_isready -h 127.0.0.1 -p 5432; do
    echo "Waiting for database..."
    sleep 1
done

PostgreSQL se reduceeste ciclo es para siempre.

Pruebe hasta que el bucle sin tiempo de espera
Pruebe hasta que el bucle sin tiempo de espera

4. Prueba timeout + + bash -c

Ahora ejecute el siguiente código en su terminal:

timeout 10s bash -c '
until pg_isready -h 127.0.0.1 -p 5432; do
    echo "Waiting for database..."
    sleep 1
done
'

Comportamiento esperado:

  • Correr durante 10 segundos.
  • Entonces timeout Mata el bucle.
  • El código de salida será 124.
$ echo $?
124
Pruebe hasta el bucle de tiempo de espera
Pruebe hasta el bucle de tiempo de espera

5. Comience PostgreSQL y vuelva a ejecutar

sudo systemctl start postgresql

Luego vuelva a ejecutar el bucle de envoltura de tiempo de espera:

timeout 10s bash -c '
until pg_isready -h 127.0.0.1 -p 5432; do
    echo "Waiting for database..."
    sleep 1
done
'

Esta vez, el ciclo debe retirarse rápidamente.

Inicie PostgreSQL y verifique si PG_ISREWY es válido
Inicie PostgreSQL y verifique si PG_ISREWY es válido

Manejar errores con gracia

Siempre debe verificar si el bucle tiene éxito o tiempos de salida. Los siguientes son:

if timeout 30s bash -c '
until pg_isready -h 127.0.0.1 -p 5432; do
    sleep 1
done
'; then
    echo "Database is up. Starting migration..."
    ./run-migrations.sh
else
    echo "Error: Database did not start in time."
    exit 1
fi

De esta manera, sus scripts avanzan de manera segura o salen con mensajes explícitos.

Bonificación: use el bucle más corto del mostrador

Si no quieres usar timeoutesta es otra forma. Número fijo de ciclos:

for i in {1..30}; do
    if pg_isready -h 127.0.0.1 -p 5432; then
        echo "Database is ready."
        ./run-migrations.sh
        exit 0
    fi
    sleep 1
done

echo "Database did not start after 30 seconds."
exit 1

Es puro carnaval, adecuado para situaciones simples.

Puntos clave

  • until Es la palabra clave bash, no un proceso. timeout No hay control directo de ello.
  • Envuelva su bucle en uno bash -c '...' Bloques para usar con él timeout.
  • Siempre verifique el estado de salida para ver si el bucle tiene éxito o falla.
  • usar pg_isready,,,,,,,,,,, para curlu otras herramientas para verificar los servicios para la salud.

en conclusión

Los bucles infinitos pueden romper sus guiones y perder el tiempo. timeout es una herramienta simple que le proporciona control. Por envolverte until En bucle en el subproceso, hace que el script sea más potente.

Este es un pequeño truco, pero puede ahorrar horas de depuración en el futuro.

Si desea mantener sus scripts bash limpios y confiables, comience a usarlos timeout hoy.

Lectura sugerida:

Publicaciones relacionadas

Deja una respuesta

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

Botón volver arriba