objectif
Empêcher une commande de bloquer indéfiniment en lui imposant un délai maximal, avec retour d’état explicite et escalade de signal.
code minimal
# stoppe la commande après 10 s (SIGTERM). exit 124 si délai dépassé.
timeout 10s commande_lente
utilisation
# délai 30 s, puis KILL au bout de 5 s supplémentaires si la commande n'a pas quitté
timeout -k 5s 30s ./job.sh
# envoyer un autre signal à l'expiration (ex: INT pour déclencher un handler)
timeout -s INT 15s make test
# protéger un pipeline entier
timeout 20s bash -lc 'producer | consumer'
# gérer les codes de sortie (124 = dépassé, 125 = erreur timeout, 126/127 = exec)
if timeout 5s curl -fsS https://data.pm/health >/dev/null; then
echo "ok"
else
rc=$?
[ "$rc" -eq 124 ] && echo "time out" || echo "échec rc=$rc"
fi
# éviter les tampons bloquants sur stdout/stderr (GNU stdbuf)
stdbuf -oL -eL timeout 10s ./script_qui_bufferise
variante(s) utile(s)
# macOS/BSD: gtimeout via coreutils (brew install coreutils)
gtimeout 10s commande
# fallback portable sans (g)timeout (utilise perl, souvent présent)
with_timeout() {
# usage: with_timeout 10 commande arg1 arg2...
perl -e '
$d=shift @ARGV; $SIG{ALRM}=sub{exit 124}; alarm $d; exec @ARGV or exit 127
' "$@"
}
with_timeout 10 sleep 20 || echo "rc=$?"
# escalade manuelle: INT puis KILL après 5 s
( sleep 10; pkill -INT -f 'serveur_local' ; sleep 5; pkill -KILL -f 'serveur_local' ) &
serveur_local
wait
# limiter un lot de tâches parallèles avec délai (xargs -P)
printf '%s\n' a b c | xargs -n1 -P4 -I{} timeout -k 2s 8s ./traite {}
notes
- par défaut,
timeoutenvoie SIGTERM à l’expiration; utilisez-kpour forcer un SIGKILL après un délai de grâce. - code de sortie: 124 si délai dépassé, 125 si
timeoutéchoue, 126/127 pour erreurs d’exécution; sinon, c’est le code de la commande. - pour des commandes interactives, certains shells nécessitent
bash -lc '...'afin de couvrir l’ensemble du pipeline. - sur macOS, utilisez
gtimeout(coreutils) ou la fonctionwith_timeoutci-dessus en fallback.