15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer
08.10.2024

Utiliser la commande `sleep` dans les scripts Bash sous Linux

La commande `sleep` sous Linux suspend l’exécution d’un script pendant une durée précisément définie — spécifiée en secondes, minutes, heures ou jours — en utilisant la syntaxe `sleep [NUMBER][SUFFIX]`. C’est l’une des primitives les plus essentielles dans les scripts Bash, permettant la limitation de débit, la logique de nouvelle tentative, la synchronisation des processus et l’automatisation temporisée sans nécessiter de planificateurs externes.

Contrairement à cron ou `at`, `sleep` fonctionne entièrement dans le contexte du processus propre au script, ce qui en fait l’outil approprié lorsque le délai doit être relatif à l’achèvement d’une commande précédente plutôt qu’à une heure absolue.

Syntaxe et référence des unités de temps

“`bash

sleep NUMBER[SUFFIX]

“`

SuffixeUnitéExempleÉquivalent en secondes
——–————————-———————–
`s`Secondes`sleep 30s`30
`m`Minutes`sleep 5m`300
`h`Heures`sleep 2h`7200
`d`Jours`sleep 1d`86400
(aucun)Secondes`sleep 10`10

Le suffixe est facultatif. Lorsqu’il est omis, l’unité par défaut est les secondes. Sur les systèmes GNU/Linux (GNU coreutils), `sleep` accepte également les valeurs à virgule flottante et les arguments multiples — une fonctionnalité absente des implémentations BSD et macOS à moins que GNU coreutils ne soit installé via Homebrew.

“`bash

GNU coreutils: both of these are valid

sleep 1.5

sleep 1m 30s # Equivalent to 90 seconds

“`

Note critique de portabilité : POSIX ne mandate que des secondes entières sans suffixe. Si votre script doit s’exécuter sur Alpine Linux (BusyBox), macOS ou AIX, limitez-vous à `sleep INTEGER` et évitez de chaîner plusieurs arguments.

Cas d’utilisation principaux dans les scripts Bash

1. Délai séquentiel entre les commandes

L’application la plus simple — insérer une pause entre deux opérations où la deuxième commande ne doit pas commencer avant qu’une condition réelle ait eu le temps de se stabiliser :

“`bash

#!/bin/bash

echo "Restarting nginx…"

systemctl restart nginx

sleep 3

systemctl status nginx

“`

La pause de 3 secondes ici tient compte de la séquence de démarrage asynchrone du gestionnaire de services. Sans elle, `status` peut signaler un état obsolète capturé avant que le processus ne soit complètement initialisé.

2. Boucle de sondage avec backoff exponentiel

Une boucle de nouvelle tentative à intervalle fixe naïve gaspille des ressources et peut amplifier la charge sur un service en difficulté. Le modèle correct est le backoff exponentiel avec gigue :

“`bash

#!/bin/bash

MAX_RETRIES=6

DELAY=2

for (( attempt=1; attempt<=MAX_RETRIES; attempt++ )); do

if curl -sf https://api.example.com/health > /dev/null; then

echo "Service healthy on attempt $attempt."

exit 0

fi

echo "Attempt $attempt failed. Retrying in ${DELAY}s…"

sleep "$DELAY"

DELAY=$(( DELAY * 2 ))

done

echo "Service unreachable after $MAX_RETRIES attempts." >&2

exit 1

“`

Cela double le temps d’attente à chaque échec : 2s, 4s, 8s, 16s, 32s, 64s. L’attente maximale totale avant d’abandonner est de 126 secondes. Ce modèle est standard dans les scripts de déploiement en production, les vérifications de santé et les pipelines CI/CD.

3. Appels API à débit limité

Lors d’interactions avec des API qui appliquent des quotas de requêtes, `sleep` impose l’intervalle requis entre les requêtes :

“`bash

#!/bin/bash

API_KEY="your_key_here"

ENDPOINTS=("users" "orders" "products" "inventory")

for endpoint in "${ENDPOINTS[@]}"; do

curl -s -H "Authorization: Bearer $API_KEY"

"https://api.example.com/v1/${endpoint}"

-o "${endpoint}.json"

echo "Fetched: $endpoint"

sleep 1 # Respect 1 req/sec rate limit

done

“`

4. Exécution de tâches en arrière-plan temporisées

L’exécution d’une commande différée sans bloquer la session shell actuelle nécessite de combiner `sleep` avec la mise en arrière-plan d’un sous-shell :

“`bash

Trigger a cache flush 60 seconds after deployment completes

( sleep 60 && redis-cli FLUSHDB ) &

echo "Cache flush scheduled. PID: $!"

“`

La variable `$!` capture le PID du sous-shell en arrière-plan, que vous pouvez ensuite utiliser avec `wait` ou `kill` si la tâche doit être annulée.

5. Boucle de surveillance et de supervision des processus

“`bash

#!/bin/bash

SERVICE="mysqld"

CHECK_INTERVAL=30

while true; do

if ! pgrep -x "$SERVICE" > /dev/null; then

echo "$(date '+%Y-%m-%d %H:%M:%S') $SERVICE not running. Restarting…"

>> /var/log/watchdog.log

systemctl start "$SERVICE"

fi

sleep "$CHECK_INTERVAL"

done

“`

Ce modèle est utilisé dans la supervision légère des processus lorsqu’un démon superviseur complet (systemd, supervisord, s6) est indisponible ou inapproprié — courant dans les environnements conteneurisés ou les instances VPS Hosting minimales.

6. Minuterie de compte à rebours avec retour utilisateur

Pour les scripts interactifs où l’opérateur a besoin de visibilité sur le temps d’attente restant :

“`bash

#!/bin/bash

COUNTDOWN=10

echo "Starting in:"

for (( i=COUNTDOWN; i>=1; i– )); do

printf "r%2d seconds remaining…" "$i"

sleep 1

done

printf "rGo! n"

“`

`printf "r"` écrase la ligne actuelle plutôt que d’ajouter de nouvelles lignes, produisant un compte à rebours propre dans le terminal.

`sleep` vs. mécanismes de temporisation alternatifs

MécanismeGranularitéBloque le shellHeure absolueCas d’utilisation
—————–—————–————–————————————————————–
`sleep`Sous-seconde (GNU)Oui (sauf `&`)NonDélais relatifs dans les scripts
`cron`1 minuteNonOuiTâches planifiées récurrentes
`at`1 minuteNonOuiExécution future ponctuelle
`systemd timer`1 secondeNonOuiTâches persistantes, journalisées et avec gestion des dépendances
`usleep` (C)MicrosecondeOuiNonPrécision au niveau noyau/C (non natif Bash)
`read -t`Sous-secondeOuiNonDélai d’attente avec saisie utilisateur optionnelle

Quand utiliser `read -t` plutôt que `sleep` : Si votre script doit se mettre en pause tout en permettant à un utilisateur d’interrompre ou de répondre pendant l’attente, `read -t SECONDS` est la primitive appropriée. Elle retourne le code de sortie 1 en cas d’expiration et 0 si l’utilisateur appuie sur Entrée, vous offrant une logique conditionnelle sans processus séparé.

“`bash

echo "Press Enter to skip the 10-second wait, or wait for automatic continuation."

read -t 10 -r || true

echo "Continuing…"

“`

Précision, virgule flottante et comportement selon la plateforme

GNU `sleep` accepte les fractions décimales, ce qui est important dans les scripts qui pilotent des animations, limitent le débit de consultation des journaux ou simulent des flux de données en temps réel :

“`bash

Tail a log file and print one line per 0.2 seconds (5 lines/sec)

while IFS= read -r line; do

echo "$line"

sleep 0.2

done < /var/log/app.log

“`

La durée réelle du sleep est un minimum, pas une garantie. L’ordonnanceur du noyau peut réveiller le processus légèrement en retard selon la charge système et la résolution du minuteur (`CONFIG_HZ`). Sur un Serveur Dédié fortement chargé exécutant des dizaines de processus simultanés, un `sleep 0.1` peut en réalité se mettre en pause pendant 0,11 à 0,15 secondes. Pour les scripts où cette dérive est inacceptable, utilisez une référence d’horloge monotone :

“`bash

#!/bin/bash

INTERVAL=5

NEXT=$(date +%s%N) # Current time in nanoseconds

while true; do

NEXT=$(( NEXT + INTERVAL * 1000000000 ))

do_work

NOW=$(date +%s%N)

REMAINING=$(( (NEXT – NOW) / 1000000 )) # Convert to milliseconds

[ "$REMAINING" -gt 0 ] && sleep "$(echo "scale=3; $REMAINING/1000" | bc)"

done

“`

Cette boucle compensant la dérive maintient un intervalle cohérent quelle que soit la durée de `do_work`.

Gestion des signaux et interruption de `sleep`

Un processus `sleep` en cours d’exécution répond aux signaux. L’envoi de `SIGALRM` au processus sleep le réveille immédiatement. Plus concrètement, appuyer sur `Ctrl+C` envoie `SIGINT` à l’ensemble du groupe de processus, terminant à la fois le script et tout `sleep` au premier plan.

Pour qu’un script gère proprement une interruption pendant un sleep :

“`bash

#!/bin/bash

cleanup() {

echo "Interrupted. Cleaning up…"

exit 1

}

trap cleanup SIGINT SIGTERM

echo "Waiting 60 seconds…"

sleep 60 &

SLEEP_PID=$!

wait "$SLEEP_PID"

echo "Wait complete."

“`

En mettant `sleep` en arrière-plan et en utilisant `wait`, le `trap` se déclenche immédiatement sur `SIGINT` plutôt que d’être différé jusqu’à la fin du sleep. C’est le modèle correct pour les scripts d’automatisation à longue durée d’exécution sur des serveurs de production.

Pièges pratiques et cas limites

Piège 1 : Utiliser `sleep` dans des boucles serrées sans condition de terminaison. Une boucle `while true; do sleep 1; done` sans chemin de sortie s’exécutera indéfiniment, consommant un emplacement de processus et s’accumulant dans la sortie `ps`. Définissez toujours un nombre maximum d’itérations ou une condition sentinelle.

Piège 2 : Supposer que `sleep` est synchrone avec les sous-shells. Lorsque vous créez un sous-shell avec `&`, le script parent n’attend pas que le `sleep` du sous-shell se termine à moins que vous n’appeliez explicitement `wait`. Cela provoque des conditions de course dans les scripts de déploiement parallèle.

Piège 3 : Coder en dur des délais pour la disponibilité des services. Utiliser `sleep 5` après le démarrage d’un service est fragile. Le service peut être prêt en 1 seconde ou prendre 30 secondes sous charge. L’alternative robuste est un sondage de disponibilité :

“`bash

#!/bin/bash

wait_for_port() {

local host="$1" port="$2" timeout="${3:-30}"

local elapsed=0

until nc -z "$host" "$port" 2>/dev/null; do

[ "$elapsed" -ge "$timeout" ] && return 1

sleep 1

(( elapsed++ ))

done

}

systemctl start postgresql

wait_for_port localhost 5432 30 && echo "PostgreSQL ready."

“`

Piège 4 : Sleep à virgule flottante sur les systèmes BusyBox. Les conteneurs Alpine Linux utilisent le `sleep` de BusyBox, qui ne prend pas en charge les décimales. Tenter `sleep 0.5` générera une erreur. Validez votre environnement avant de déployer des scripts qui reposent sur une précision inférieure à la seconde.

Intégration de `sleep` dans les flux de travail automatisés de serveurs

Sur un VPS avec cPanel géré, les scripts de maintenance automatisés combinent fréquemment `sleep` avec cron pour implémenter une planification inférieure à la minute. Puisque la résolution minimale de cron est d’une minute, vous pouvez obtenir des intervalles de 15 secondes comme ceci :

“`bash

crontab entry — runs the script 4 times per minute

  • * * * * /usr/local/bin/check_queue.sh
  • * * * * sleep 15 && /usr/local/bin/check_queue.sh
  • * * * * sleep 30 && /usr/local/bin/check_queue.sh
  • * * * * sleep 45 && /usr/local/bin/check_queue.sh

“`

Cette technique est largement utilisée pour les processeurs de files d’attente, les vérifications de santé et les collecteurs de métriques sur une infrastructure partagée où l’installation d’un planificateur de tâches dédié n’est pas autorisée.

Pour les scripts de renouvellement de certificats SSL, `sleep` fournit le délai entre les tentatives lorsque la propagation du défi ACME nécessite l’expiration du TTL DNS avant que l’AC puisse vérifier la propriété. Si vous gérez des certificats sur votre propre infrastructure, les Certificats SSL avec des pipelines de renouvellement automatisé bénéficient d’intervalles de nouvelle tentative précisément ajustés.

De même, les scripts de vérification de propagation de domaine — utiles après la mise à jour des enregistrements via l’Enregistrement de domaine — utilisent des boucles `sleep` pour interroger les résolveurs DNS à des intervalles alignés sur les valeurs TTL attendues.

Matrice de décision : choisir la bonne stratégie de délai

ScénarioApproche recommandée
———————————————–—————————————————
Pause fixe entre deux commandes séquentielles`sleep N`
Nouvelle tentative jusqu’au succès, éviter l’effet de troupeauBackoff exponentiel avec `sleep`
Tâche récurrente toutes les N minutes`cron` (pas `sleep`)
Tâche récurrente inférieure à la minute`cron` + astuce de décalage `sleep`
Délai sans bloquer le terminal`( sleep N && command ) &`
Pause avec possibilité d’interruption utilisateur`sleep N &` + `wait $!` + `trap`
Vérification de disponibilité du serviceBoucle de sondage port/santé avec `sleep 1` par tentative
Intervalle haute précision (compensation de dérive)Référence d’horloge monotone avec `sleep` calculé
Délai sous-seconde sur Alpine/BusyBoxÀ éviter ; utiliser des secondes entières ou changer d’image de base

Points techniques clés à retenir

  • Utilisez toujours `sleep "$VARIABLE"` avec des guillemets doubles pour éviter les bugs de découpage de mots lorsque la variable contient une décimale.
  • Préférez `sleep 1m 30s` à `sleep 90` pour la lisibilité dans les scripts de maintenance à longue durée d’exécution.
  • Mettez `sleep` en arrière-plan avec `wait` et un `trap` chaque fois que votre script doit répondre aux signaux pendant la pause.
  • N’utilisez jamais un `sleep` codé en dur comme substitut à une vérification de disponibilité appropriée — utilisez une boucle de sondage avec un délai d’expiration.
  • Validez le comportement de `sleep` sur le système d’exploitation cible avant de déployer des scripts utilisant une syntaxe à virgule flottante ou à arguments multiples.
  • Sur les serveurs de production, journalisez l’horodatage avant et après les appels `sleep` longs pour détecter la dérive de l’ordonnanceur lors des analyses post-incident.
  • Lors de la création d’automatisations sur des Panneaux de contrôle VPS, vérifiez si le planificateur de tâches du panneau fournit déjà un contrôle d’intervalle avant d’ajouter manuellement une logique `sleep`.

FAQ

`sleep` consomme-t-il du CPU pendant l’attente ?

Non. `sleep` appelle `nanosleep()` (ou équivalent) au niveau du noyau, plaçant le processus dans un état de sleep interruptible (`S` dans la sortie `ps`). Il ne consomme aucun cycle CPU pendant l’attente — seulement une petite quantité de mémoire pour l’entrée du processus dans la table des processus.

Quelle est la valeur maximale acceptée par `sleep` ?

Sur GNU/Linux, `sleep` accepte des valeurs jusqu’aux limites d’un nombre à virgule flottante `double`, ce qui est effectivement illimité à des fins pratiques. `sleep 1d` (86400 secondes) est courant ; `sleep 365d` est valide. La limite pratique est la durée de fonctionnement du système.

Pourquoi `sleep 0.5` échoue-t-il sur mon conteneur Docker ?

Alpine Linux utilise BusyBox, dont l’implémentation de `sleep` n’accepte que des secondes entières. Passez à une image de base Debian ou Ubuntu, ou installez GNU coreutils (`apk add coreutils`) pour activer la prise en charge des décimales.

Puis-je annuler un processus `sleep` mis en arrière-plan ?

Oui. Capturez son PID avec `SLEEP_PID=$!` immédiatement après l’avoir mis en arrière-plan, puis utilisez `kill "$SLEEP_PID"` pour le terminer. Si vous avez utilisé `( sleep N && command ) &`, tuer le PID du sous-shell empêchera également l’exécution de la commande suivante.

Est-il sûr d’utiliser `sleep` dans le script `ExecStart` d’une unité de service `systemd` ?

Oui, mais avec des mises en garde. Si l’unité de service a `TimeoutStartSec` défini, un long `sleep` pendant le démarrage amènera systemd à tuer le service comme un démarrage échoué. Pour les délais post-démarrage, utilisez `ExecStartPost` avec un sondage de disponibilité, ou configurez `Type=forking` avec une gestion appropriée des fichiers PID plutôt que de compter sur `sleep` pour différer l’initialisation.

15%

Économisez 15% sur tous les services d'hébergement

Testez vos compétences et obtenez Réduction sur tout plan d'hébergement

Utilisez le code :

Skills
Commencer