118 votes

Dormir jusqu'à une heure/date spécifique

Je veux que mon script bash dorme jusqu'à une heure spécifique. Ainsi, je veux une commande comme "sleep" qui ne prend pas d'intervalle mais une heure de fin et qui dort jusqu'à cette heure.

Le démon "at" n'est pas une solution, car j'ai besoin de bloquer un script en cours d'exécution jusqu'à une certaine date/heure.

Y a-t-il une telle commande?

2 votes

Veuillez noter que la solution qui utilise simplement un long sleep suivi d'un calcul peut dormir trop longtemps, peut-être beaucoup trop longtemps, surtout si vous avez une machine qui peut hiberner. La commande de sommeil posix ne garantit pas de ne pas dormir trop longtemps. La solution de @Camusensei aborde très bien cette préoccupation.

119voto

SpoonMeiser Points 6211

Comme mentionné par Outlaw Programmer, je pense que la solution est simplement de dormir pendant le nombre correct de secondes.

Pour ce faire en bash, faites ce qui suit:

current_epoch=$(date +%s)
target_epoch=$(date -d '01/01/2010 12:00' +%s)

sleep_seconds=$(( $target_epoch - $current_epoch ))

sleep $sleep_seconds

Pour ajouter une précision jusqu'aux nanosecondes (effectivement plus proche des millisecondes) utilisez par exemple cette syntaxe:

current_epoch=$(date +%s.%N)
target_epoch=$(date -d "20:25:00.12345" +%s.%N)

sleep_seconds=$(echo "$target_epoch - $current_epoch"|bc)

sleep $sleep_seconds

Notez que macOS / OS X ne prend pas en charge la précision en dessous des secondes, vous devriez utiliser coreutils de brew à la place → voir ces instructions

8 votes

Merci pour ça, j'ai écrit un petit script shell pour obtenir une commande "sleepuntil".

1 votes

@enigmaticPhysicist: Il existe une commande similaire appelée "at", qui s'exécute de manière asynchrone.

9 votes

Si vous voulez arrêter demain à 3h du matin, vous pouvez utiliser target_epoch = $ (date -d 'demain 03:00' +% s) à la place.

25voto

John Feminella Points 116878

Utilisez sleep, mais calculez le temps en utilisant date. Vous voudrez utiliser date -d pour cela. Par exemple, disons que vous vouliez attendre jusqu'à la semaine prochaine :

expr `date -d "next week" +%s` - `date -d "now" +%s`

Remplacez simplement "next week" par la date pour laquelle vous souhaitez attendre, puis attribuez cette expression à une valeur et attendez ce nombre de secondes :

startTime=$(date +%s)
endTime=$(date -d "next week" +%s)
timeToWait=$(($endTime- $startTime))
sleep $timeToWait

C'est tout !

0 votes

Il vaut la peine de préciser comment vous attribueriez la valeur à une variable, car timeToWait=expr ... ne fonctionnera pas directement, et vous ne pouvez pas utiliser de backticks car ils ne se nichent pas, vous devrez donc utiliser $(), ou des variables temporaires.

0 votes

Bonne suggestion; Je vais modifier la mienne pour la rendre plus claire afin que les gens ne se fassent pas de fausses idées.

0 votes

Note -d est une extension non-POSIX à la commande date. Sur FreeBSD, elle tente de définir la valeur du noyau pour l'heure d'été.

9voto

SpoonMeiser Points 6211

Vous pouvez arrêter un processus en cours d'exécution en lui envoyant un signal SIGSTOP, puis le faire reprendre en envoyant un signal SIGCONT.

Vous pourriez donc arrêter votre script en lui envoyant un SIGSTOP :

kill -SIGSTOP 

Et ensuite utiliser le démon at pour le réveiller en lui envoyant un SIGCONT de la même manière.

Probablement, votre script informera at de l'heure à laquelle il voulait être réveillé avant de se mettre en veille.

8voto

kolomer Points 31

J'ai voulu un script qui vérifiait uniquement les heures et les minutes afin de pouvoir exécuter le script avec les mêmes paramètres chaque jour. Je ne veux pas m'inquiéter de quel jour sera demain. J'ai donc opté pour une approche différente.

target="$1.$2"
cur=$(date '+%H.%M')
while test $target != $cur; do
    sleep 59
    cur=$(date '+%H.%M')
done

les paramètres du script sont les heures et les minutes, donc je peux écrire quelque chose comme:

til 7 45 && mplayer song.ogg

(til est le nom du script)

plus de journées de retard au travail parce que vous avez mal tapé le jour. Cheers!

0 votes

Un détail très mineur si la précision est importante : si juste avant la date limite (<1 minute), il attend toujours au moins 59 secondes. De plus, ce script ne fonctionne pas exactement à l'heure 59 fois sur 60 en moyenne.

0 votes

Au fait, vous pouvez facilement encapsuler le code dans une fonction (aucun changement de code nécessaire) et l'appeler à l'intérieur d'un script shell comme ceci jusqu'à 7h45

7voto

Dennis Williamson Points 105818

Pour faire suite à la réponse de SpoonMeiser, voici un exemple spécifique :

$cat ./reviveself

#!/bin/bash

# sauvegarder mon ID de processus
rspid=$$

# programmer ma propre résurrection
# /bin/sh semble ne pas aimer la forme SIGCONT, donc j'utilise CONT
# at peut accepter des dates et heures spécifiques ainsi que des dates relatives
# vous pouvez même faire quelque chose comme "at jeudi" qui se produirait toutes les
# multiples de 24 heures plutôt que le début de la journée
echo "kill -CONT $rspid"|at now + 2 minutes

# me mettre inconscient
# bash est heureux avec les signaux symboliques
kill -SIGSTOP $rspid

# faire quelque chose pour prouver que je suis en vie
date>>reviveself.out
$

0 votes

Je pense que vous voulez planifier un SIGCONT, plutôt qu'un autre SIGSTOP, donc soit le signal, soit le commentaire est incorrect. Sinon, c'est sympa de voir un exemple approprié.

0 votes

Oops, j'ai tapé une faute de frappe dans le commentaire. Maintenant corrigé. Mais faites attention à utiliser des signaux numériques, car ils peuvent être différents.

0 votes

J'ai trouvé que dash ne semble pas comprendre SIGCONT, donc au début j'ai utilisé -18 qui n'est pas portable, puis j'ai découvert qu'il aimait CONT, donc j'ai modifié la réponse ci-dessus pour corriger cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X