Je suis surpris que personne n'ait utilisé l'outil sleepenh
dans leurs scripts. Au lieu de cela, les solutions proposées utilisent soit un sleep 1
entre les sorties des minuteurs consécutifs, soit une boucle occupée qui produit des sorties aussi rapidement que possible. La première est insuffisante car en raison du peu de temps passé à imprimer, la sortie ne se fera pas effectivement une fois par seconde mais un peu moins que cela, ce qui est suboptimal. Après suffisamment de temps écoulé, le compteur sautera une seconde. La seconde est insuffisante car elle maintient le processeur occupé pour aucune bonne raison.
L'outil que j'ai dans mon $PATH
ressemble à ceci :
#!/bin/sh
if [ $# -eq 0 ]; then
TIMESTAMP=$(sleepenh 0)
before=$(date +%s)
while true; do
diff=$(($(date +%s) - before))
printf "%02d:%02d:%02d\r" $((diff/3600)) $(((diff%3600)/60)) $((diff%60))
TIMESTAMP=$(sleepenh $TIMESTAMP 1.0);
done
exit 1 # cela ne doit jamais être atteint
fi
echo "Décompte jusqu'à $@"
"$0" &
counterpid=$!
trap "exit" INT TERM
trap "kill 0" EXIT
sleep "$@"
kill $counterpid
Le script peut être utilisé comme chronomètre (décompte jusqu'à ce qu'il soit interrompu) ou comme minuterie qui fonctionne pendant la durée spécifiée. Comme la commande sleep
est utilisée, ce script permet de spécifier la durée pendant laquelle compter avec la même précision que votre commande sleep
le permet. Sur Debian et dérivés, cela comprend les attentes sous-secondes et une manière agréable, lisible par un humain, de spécifier le temps. Donc, par exemple, vous pouvez dire :
$ time countdown 2m 4.6s
compte à rebours de 2m 4.6s 0.00s utilisateur 0.00s système 0% cpu 2:04.60 total
Et comme vous pouvez le voir, la commande a fonctionné exactement pendant 2 minutes et 4,6 secondes sans trop de magie dans le script lui-même.
ÉDITER:
L'outil sleepenh provient du paquet du même nom dans Debian et ses dérivés comme Ubuntu. Pour les distributions qui ne l'ont pas, il vient de https://github.com/nsc-deb/sleepenh
L'avantage de sleepenh est qu'il est capable de prendre en compte le petit retard qui s'accumule au fil du temps à partir du traitement d'autres choses que du sommeil pendant une boucle. Même si l'on ne ferait que sleep 1
dans une boucle 10 fois, l'exécution globale prendrait un peu plus de 10 secondes en raison du petit surcoût provenant de l'exécution de sleep
et de l'itération de la boucle. Cette erreur s'accumule lentement et rendrait notre minuterie de chronomètre de plus en plus imprécise au fil du temps. Pour résoudre ce problème, il faut à chaque itération de la boucle calculer le temps précis de sommeil, qui est généralement légèrement inférieur à une seconde (pour des minuteurs d'intervalle d'une seconde). L'outil sleepenh le fait pour vous.