Je lance cette boucle pour vérifier et imprimer certaines choses à chaque seconde. Cependant, comme les calculs prennent peut-être quelques centaines de millisecondes, le temps imprimé saute parfois une seconde.
Existe-t-il un moyen d'écrire une telle boucle que je sois assuré d'obtenir une impression à chaque seconde? (À condition bien sûr que les calculs dans la boucle prennent moins d'une seconde :))
while true; do
TIME=$(date +%H:%M:%S)
# some calculations which take a few hundred milliseconds
FOO=...
BAR=...
printf '%s %s %s\n' $TIME $FOO $BAR
sleep 1
done
bash
timestamps
sleep
en avant
la source
la source
sched(7)
API (POSIX: voir<sched.h>
et les pages liées à partir de là), vous ne pouvez en principe pas avoir de garanties en temps réel de ce formulaire.Réponses:
Pour rester un peu plus proche du code d'origine, ce que je fais est:
Cela change un peu la sémantique: si vos fichiers ont pris moins d'une seconde, ils attendront simplement que la seconde soit complète. Cependant, si votre travail prend plus d'une seconde pour une raison quelconque, il ne créera pas encore plus de sous-processus sans fin.
Ainsi, vos données ne sont jamais exécutées en parallèle et non en arrière-plan, de sorte que les variables fonctionnent également comme prévu.
Notez que si vous démarrez également des tâches d'arrière-plan supplémentaires, vous devez modifier l'
wait
instruction pour n'attendre que lesleep
processus en particulier.Si vous avez besoin d’être encore plus précis, vous devrez probablement le synchroniser avec l’horloge système et le mode veille au lieu de quelques secondes.
Comment synchroniser avec l'horloge système? Aucune idée vraiment, tentative stupide:
Défaut:
Sortie: 003511461 010510925 016081282 021643477 028504349 03 ... (continue de croître)
Synced:
Sortie: 002648691 001098397 002514348 001293023 001679137 00 ... (reste identique)
la source
sleep
manipuler des fractions de secondes?sleep 0.9 || sleep 1
car un paramètre invalide est à peu près la seule raison pour laquelle le sommeil échoue.sleep 0.9
à être interprété comme unesleep 0
implémentation naïve (étant donné que c'est ce queatoi
nous ferions). Je ne sais pas si cela entraînerait une erreur.gdate
sur macOS pour fairedate +%N
fonctionner.)Si vous pouvez restructurer votre boucle dans un script / oneliner puis façon de faire la plus simple est avec
watch
et sonprecise
option.Vous pouvez voir l’effet avec
watch -n 1 sleep 0.5
- il indiquera le nombre de secondes comptées, mais sautera parfois une seconde. Courir commewatch -n 1 -p sleep 0.5
volonté sortie deux fois par seconde, chaque seconde, et vous ne verrez pas skips.la source
L'exécution des opérations dans un sous-shell fonctionnant en tâche de fond les empêcherait d'interférer autant avec le
sleep
.Le seul temps "volé" de la seconde serait le temps nécessaire au lancement du sous-shell, de sorte qu'il sera éventuellement sauté une seconde, mais espérons-le moins souvent que le code d'origine.
Si le code dans le sous-shell utilise plus d'une seconde, la boucle commence à accumuler des travaux en arrière-plan et finit par manquer de ressources.
la source
Une autre alternative (si vous ne pouvez pas utiliser, par exemple,
watch -p
comme le suggère Maelstrom) estsleepenh
[ page de manuel ], qui est conçue pour cela.Exemple:
Notez
sleep 0.2
que la simulation simule une tâche fastidieuse qui consomme environ 200 ms. Malgré cela, la sortie en nanosecondes reste stable (enfin, par rapport aux normes des systèmes d’exploitation non temps réel) - cela se produit une fois par seconde:C'est sous 1ms différent, et pas de tendance. C'est très bien; vous devez vous attendre à des rebonds d'au moins 10 ms s'il y a une charge sur le système, mais pas de dérive dans le temps. C'est-à-dire que vous ne perdrez pas une seconde.
la source
Avec
zsh
:Si votre sommeil ne prend pas en charge les secondes en virgule flottante, vous pouvez utiliser celui
zsh
dezselect
(après azmodload zsh/zselect
):Celles-ci ne doivent pas dériver tant que les commandes de la boucle prennent moins d'une seconde à s'exécuter.
la source
J'avais exactement la même exigence pour un script shell POSIX, où toutes les aides (usleep, GNUsleep, sleepenh, ...) ne sont pas disponibles.
voir: https://stackoverflow.com/a/54494216
la source