Dormez jusqu'à une heure / date précise

89

Je veux que mon script bash s'endorme jusqu'à une heure précise. Donc, je veux une commande comme "sleep" qui ne prend aucun intervalle mais une heure de fin et dort jusque-là.

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

Existe-t-il une telle commande?

theomega
la source
1
Notez que la solution qui utilise simplement un long sommeil précédé d'un calcul peut dormir trop longtemps, peut-être beaucoup trop longtemps surtout si vous avez une machine qui peut passer en veille prolongée. La commande posix sleep ne promet pas de ne pas dormir trop longtemps. La solution de @Camusensei répond très bien au problème.
GregD

Réponses:

98

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

Pour ce faire dans bash, procédez comme 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 de la précision jusqu'à nanosecondes (effectivement plus d'environ 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 inférieure à quelques secondes, vous devrez utiliser coreutilsà la brewplace → voir ces instructions

CuillèreMeiser
la source
8
Merci pour cela, j'ai écrit un petit script shell pour obtenir une commande "sleepuntil".
theomega
1
@enigmaticPhysicist: Il existe un appel de commande similaire "at", qui s'exécute de manière asynchrone.
voidlogic
6
Si vous souhaitez vous arrêter demain à 3 heures du matin, vous pouvez utiliser à la target_epoch=$(date -d 'tomorrow 03:00' +%s)place.
Yajo le
Vous pouvez faire de même en utilisant une fourchette au datelieu de deux! Voir 1ère partie de ma réponse
F.Hauri
1
Notez que cette solution peut potentiellement dormir trop longtemps, et si votre machine hiberne un peu, cela peut être beaucoup trop long.
GregD
23

Comme cette question a été posée il y a 4 ans, cette première partie concerne les anciennes versions de bash:

Dernière édition: mercredi 22 avril 2020, quelque chose entre 10h30 et 10h: 55 (Important pour la lecture d'échantillons)

Méthode générale (évitez les fourches inutiles!)

(Nota: cette méthode utilise date -fqui n'est pas POSIX et ne fonctionne pas sous MacOS! Si sous Mac, allez à mon purfonction )

Afin de réduire forks, au lieu de courir datedeux fois, je préfère utiliser ceci:

Échantillon de départ simple

sleep $(($(date -f - +%s- <<< $'tomorrow 21:30\nnow')0))

tomorrow 21:30pourrait être remplacé par tout type de date et de format reconnu par date, à l'avenir.

Avec haute précision (nanosec)

Presque pareil:

sleep $(bc <<<s$(date -f - +'t=%s.%N;' <<<$'07:00 tomorrow\nnow')'st-t')

Atteindre prochaine fois

Pour atteindre le prochainHH:MM sens aujourd'hui si possible, demain si trop tard:

sleep $((($(date -f - +%s- <<<$'21:30 tomorrow\nnow')0)%86400))

Cela fonctionne sous , et d'autres shells modernes, mais vous devez utiliser:

sleep $(( ( $(printf 'tomorrow 21:30\nnow\n' | date -f - +%s-)0 )%86400 ))

sous plus léger coques comme ou .

Pur façon, pas de fourchette !!

Testé sous MacOS!

J'ai écrit une deux petites fonctions: sleepUntiletsleepUntilHires

 Syntax:
 sleepUntil [-q] <HH[:MM[:SS]]> [more days]
     -q Quiet: don't print sleep computed argument
     HH          Hours (minimal required argument)
     MM          Minutes (00 if not set)
     SS          Seconds (00 if not set)
     more days   multiplied by 86400 (0 by default)

Comme les nouvelles versions de bash offrent une printfoption pour récupérer la date, pour cette nouvelle façon de dormir jusqu'à HH: MM sans utiliser dateou tout autre fork, j'ai construit un peufonction. C'est ici:

sleepUntil() { # args [-q] <HH[:MM[:SS]]> [more days]
    local slp tzoff now quiet=false
    [ "$1" = "-q" ] && shift && quiet=true
    local -a hms=(${1//:/ })
    printf -v now '%(%s)T' -1
    printf -v tzoff '%(%z)T\n' $now
    tzoff=$((0${tzoff:0:1}(3600*${tzoff:1:2}+60*${tzoff:3:2})))
    slp=$((
       ( 86400+(now-now%86400) + 10#$hms*3600 + 10#${hms[1]}*60 + 
         ${hms[2]}-tzoff-now ) %86400 + ${2:-0}*86400
    ))
    $quiet || printf 'sleep %ss, -> %(%c)T\n' $slp $((now+slp))
    sleep $slp
}

Ensuite:

sleepUntil 10:37 ; date +"Now, it is: %T"
sleep 49s, -> Wed Apr 22 10:37:00 2020
Now, it is: 10:37:00

sleepUntil -q 10:37:44 ; date +"Now, it is: %T"
Now, it is: 10:37:44

sleepUntil 10:50 1 ; date +"Now, it is: %T"
sleep 86675s, -> Thu Apr 23 10:50:00 2020
^C

Si l'objectif est avant, cela dormira jusqu'à demain:

sleepUntil 10:30 ; date +"Now, it is: %T"
sleep 85417s, -> Thu Apr 23 10:30:00 2020
^C

sleepUntil 10:30 1 ; date +"Now, it is: %T"
sleep 171825s, -> Fri Apr 24 10:30:00 2020
^C

Temps HiRes avec sous GNU / Linux

Récent , à partir de la version 5.0, ajoutez une nouvelle $EPOCHREALTIMEvariable en microsecondes. De là, il y a une sleepUntilHiresfonction.

sleepUntilHires () { # args [-q] <HH[:MM[:SS]]> [more days]
    local slp tzoff now quiet=false musec musleep;
    [ "$1" = "-q" ] && shift && quiet=true;
    local -a hms=(${1//:/ });
    printf -v now '%(%s)T' -1;
    IFS=. read now musec <<< $EPOCHREALTIME;
    musleep=$[2000000-10#$musec];
    printf -v tzoff '%(%z)T\n' $now;
    tzoff=$((0${tzoff:0:1}(3600*${tzoff:1:2}+60*${tzoff:3:2})));
    slp=$(((( 86400 + ( now - now%86400 ) +
            10#$hms*3600+10#${hms[1]}*60+10#${hms[2]} -
            tzoff - now - 1
            ) % 86400 ) + ${2:-0} * 86400
          )).${musleep:1};
    $quiet || printf 'sleep %ss, -> %(%c)T\n' $slp $((now+${slp%.*}+1));
    read -t $slp foo
}

Remarque: cette utilisation read -test intégrée à la place de sleep. Malheureusement, cela ne fonctionnera pas lors de l'exécution en arrière-plan, sans vrai TTY. N'hésitez pas à remplacer read -tpar sleepsi vous prévoyez d'exécuter ceci dans des scripts d'arrière-plan ... (Mais pour le processus d'arrière-plan, envisagez d'utiliser cronet / ou à la atplace de tout cela)

Passer le paragraphe suivant pour les tests et les avertissements sur $ËPOCHSECONDS!

Le noyau récent évite d'utiliser /proc/timer_listpar l'utilisateur !!

Sous le noyau Linux récent, vous trouverez un fichier de variables nommé `/ proc / timer_list` où vous pourrez lire un` offset` et une variable `now`, en ** nanosecondes **. Nous pouvons donc calculer le temps de sommeil pour atteindre le temps * très haut * souhaité.

(J'ai écrit ceci pour générer et suivre des événements spécifiques sur de très gros fichiers journaux, contenant mille lignes pendant une seconde).

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_SKIP=$_i
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
    TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
     break
done
unset _i _timer_list
readonly TIMER_LIST_OFFSET TIMER_LIST_SKIP

sleepUntilHires() {
    local slp tzoff now quiet=false nsnow nsslp
    [ "$1" = "-q" ] && shift && quiet=true
    local hms=(${1//:/ })
    mapfile -n 1 -s $TIMER_LIST_SKIP nsnow </proc/timer_list
    printf -v now '%(%s)T' -1
    printf -v tzoff '%(%z)T\n' $now
    nsnow=$((${nsnow//[a-z ]}+TIMER_LIST_OFFSET))
    nsslp=$((2000000000-10#${nsnow:${#nsnow}-9}))
    tzoff=$((0${tzoff:0:1}(3600*${tzoff:1:2}+60*${tzoff:3:2})))
    slp=$(( ( 86400 + ( now - now%86400 ) +
            10#$hms*3600+10#${hms[1]}*60+${hms[2]} -
            tzoff - now - 1
        ) % 86400)).${nsslp:1}
    $quiet || printf 'sleep %ss, -> %(%c)T\n' $slp $((now+${slp%.*}+1))
    sleep $slp
}

Après avoir défini deux variables en lecture seule , TIMER_LIST_OFFSETet TIMER_LIST_SKIP, la fonction accédera très rapidement au fichier de variables /proc/timer_listpour le calcul du temps de sommeil:

Petite fonction de test

tstSleepUntilHires () { 
    local now next last
    printf -v next "%(%H:%M:%S)T" $((${EPOCHREALTIME%.*}+1))
    sleepUntilHires $next
    date -f - +%F-%T.%N < <(echo now;sleep .92;echo now)
    printf -v next "%(%H:%M:%S)T" $((${EPOCHREALTIME%.*}+1))
    sleepUntilHires $next
    date +%F-%T.%N
}

Peut rendre quelque chose comme:

sleep 0.244040s, -> Wed Apr 22 10:34:39 2020
2020-04-22-10:34:39.001685312
2020-04-22-10:34:39.922291769
sleep 0.077012s, -> Wed Apr 22 10:34:40 2020
2020-04-22-10:34:40.004264869
  • Au début de la seconde suivante,
  • temps d'impression, puis
  • attendez 0,92 seconde, puis
  • temps d'impression, puis
  • calculer 0,07 seconde à la seconde suivante
  • dormir 0,07 seconde, puis
  • temps d'impression.

Attention à ne pas mélanger $EPOCHSECONDet $EPOCHREALTIME!

Lisez mon avertissement sur la différence entre $EPOCHSECONDet$EPOCHREALTIME

Cette fonction est utilisée, $EPOCHREALTIMEdonc ne l'utilisez pas $EPOCHSECONDpour établir la seconde suivante :

Exemple de problème: tentative d'impression de l'heure suivante arrondie de 2 secondes:

for i in 1 2;do
    printf -v nextH "%(%T)T" $(((EPOCHSECONDS/2)*2+2))
    sleepUntilHires $nextH
    IFS=. read now musec <<<$EPOCHREALTIME
    printf "%(%c)T.%s\n" $now $musec
done

Peut produire:

sleep 0.587936s, -> Wed Apr 22 10:51:26 2020
Wed Apr 22 10:51:26 2020.000630
sleep 86399.998797s, -> Thu Apr 23 10:51:26 2020
^C
F. Hauri
la source
1
Hou la la! Calculer des nanosecondes sous bash !
F.Hauri
Calculer des micro secondes sous natif bash v5 + !!
F.Hauri le
21

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

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

Remplacez simplement "la semaine prochaine" par la date que vous souhaitez attendre, puis attribuez cette expression à une valeur et dormez pendant autant de secondes:

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

Terminé!

John Feminella
la source
Cela vaut la peine de développer la façon dont vous attribueriez la valeur à une variable, puisque timeToWait = expr ... ne fonctionnera pas directement, et vous ne pouvez pas utiliser de backticks car ils ne s'emboîtent pas, vous devrez donc utiliser $ () ou des variables temporaires.
SpoonMeiser
Bonne suggestion; Je vais modifier le mien pour que cela soit plus clair afin que les gens ne se fassent pas une idée fausse.
John Feminella
Remarque -dest une extension non POSIX à ce jour. Sur FreeBSD, il essaie de définir la valeur du noyau pour l'heure d'été.
Dave C le
9

Voici une solution qui fait le travail ET informe l'utilisateur du temps restant. Je l'utilise presque tous les jours pour exécuter des scripts pendant la nuit (en utilisant cygwin, car je ne pouvais pas crontravailler sous Windows)

traits

  • Précis jusqu'à la seconde
  • Détecte les changements d'heure système et s'adapte
  • Sortie intelligente indiquant le temps restant
  • Format d'entrée sur 24 heures
  • retourne true pour pouvoir enchaîner avec &&

Exemple d'exécution

$ til 13:00 && date
1 hour and 18 minutes and 26 seconds left...
1 hour and 18 minutes left...
1 hour and 17 minutes left...
1 hour and 16 minutes left...
1 hour and 15 minutes left...
1 hour and 14 minutes left...
1 hour and 10 minutes left...
1 hour and  5 minutes left...
1 hour and  0 minutes left...
55 minutes left...
50 minutes left...
45 minutes left...
40 minutes left...
35 minutes left...
30 minutes left...
25 minutes left...
20 minutes left...
15 minutes left...
10 minutes left...
 5 minutes left...
 4 minutes left...
 3 minutes left...
 2 minutes left...
 1 minute left...
Mon, May 18, 2015  1:00:00 PM

(La date à la fin ne fait pas partie de la fonction, mais en raison de la && date)

Code

til(){
  local hour mins target now left initial sleft correction m sec h hm hs ms ss showSeconds toSleep
  showSeconds=true
  [[ $1 =~ ([0-9][0-9]):([0-9][0-9]) ]] || { echo >&2 "USAGE: til HH:MM"; return 1; }
  hour=${BASH_REMATCH[1]} mins=${BASH_REMATCH[2]}
  target=$(date +%s -d "$hour:$mins") || return 1
  now=$(date +%s)
  (( target > now )) || target=$(date +%s -d "tomorrow $hour:$mins")
  left=$((target - now))
  initial=$left
  while (( left > 0 )); do
    if (( initial - left < 300 )) || (( left < 300 )) || [[ ${left: -2} == 00 ]]; then
      # We enter this condition:
      # - once every 5 minutes
      # - every minute for 5 minutes after the start
      # - every minute for 5 minutes before the end
      # Here, we will print how much time is left, and re-synchronize the clock

      hs= ms= ss=
      m=$((left/60)) sec=$((left%60)) # minutes and seconds left
      h=$((m/60)) hm=$((m%60)) # hours and minutes left

      # Re-synchronise
      now=$(date +%s) sleft=$((target - now)) # recalculate time left, multiple 60s sleeps and date calls have some overhead.
      correction=$((sleft-left))
      if (( ${correction#-} > 59 )); then
        echo "System time change detected..."
        (( sleft <= 0 )) && return # terminating as the desired time passed already
        til "$1" && return # resuming the timer anew with the new time
      fi

      # plural calculations
      (( sec > 1 )) && ss=s
      (( hm != 1 )) && ms=s
      (( h > 1 )) && hs=s

      (( h > 0 )) && printf %s "$h hour$hs and "
      (( h > 0 || hm > 0 )) && printf '%2d %s' "$hm" "minute$ms"
      if [[ $showSeconds ]]; then
        showSeconds=
        (( h > 0 || hm > 0 )) && (( sec > 0 )) && printf %s " and "
        (( sec > 0 )) && printf %s "$sec second$ss"
        echo " left..."
        (( sec > 0 )) && sleep "$sec" && left=$((left-sec)) && continue
      else
        echo " left..."
      fi
    fi
    left=$((left-60))
    sleep "$((60+correction))"
    correction=0
  done
}
Camusensei
la source
8

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

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

kill -SIGSTOP <pid>

Et puis utilisez le at deamon pour le réveiller en lui envoyant un SIGCONT de la même manière.

Vraisemblablement, votre script vous informera du moment où il a voulu être réveillé avant de s'endormir.

CuillèreMeiser
la source
8

Sur Ubuntu 12.04.4 LTS, voici la simple entrée bash qui fonctionne:

sleep $(expr `date -d "03/21/2014 12:30" +%s` - `date +%s`)
Anthony O.
la source
7

Pour suivre la réponse de SpoonMeiser, voici un exemple spécifique:

$cat ./reviveself

#!/bin/bash

# save my process ID
rspid=$$

# schedule my own resuscitation
# /bin/sh seems to dislike the SIGCONT form, so I use CONT
# at can accept specific dates and times as well as relative ones
# you can even do something like "at thursday" which would occur on a 
# multiple of 24 hours rather than the beginning of the day
echo "kill -CONT $rspid"|at now + 2 minutes

# knock myself unconscious
# bash is happy with symbolic signals
kill -SIGSTOP $rspid

# do something to prove I'm alive
date>>reviveself.out
$
Suspendu jusqu'à nouvel ordre.
la source
Je pense que vous voulez programmer un SIGCONT, plutôt qu'un autre SIGSTOP, donc soit le signal, soit le commentaire est faux. Sinon, agréable de voir un bon exemple.
SpoonMeiser
Oups, j'ai tapé dans le commentaire. Maintenant corrigé. Mais vous devez regarder en utilisant des signaux numériques, car ils peuvent être différents.
Suspendu jusqu'à nouvel ordre.
J'ai trouvé que le tableau de bord semble ne pas comprendre SIGCONT, donc au début, j'ai utilisé -18 qui n'est pas portable, puis j'ai trouvé qu'il aime CONT, alors j'ai modifié la réponse ci-dessus pour résoudre ce problème.
Suspendu jusqu'à nouvel ordre.
6

Je voulais un script qui ne vérifiait que 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 utilisé 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 jours de retard au travail parce que vous avez mal saisi la journée. à votre santé!

Kolomer
la source
4

timeToWait = $ (($ end - $ start))

Attention, "timeToWait" pourrait être un nombre négatif! (par exemple, si vous spécifiez de dormir jusqu'à "15:57" et maintenant c'est "15:58"). Vous devez donc le vérifier pour éviter des erreurs de message étranges:

#!/bin/bash
set -o nounset

### // Sleep until some date/time. 
# // Example: sleepuntil 15:57; kdialog --msgbox "Backup needs to be done."


error() {
  echo "$@" >&2
  exit 1;
}

NAME_PROGRAM=$(basename "$0")

if [[ $# != 1 ]]; then
     error "ERROR: program \"$NAME_PROGRAM\" needs 1 parameter and it has received: $#." 
fi


current=$(date +%s.%N)
target=$(date -d "$1" +%s.%N)

seconds=$(echo "scale=9; $target - $current" | bc)

signchar=${seconds:0:1}
if [ "$signchar" = "-" ]; then
     error "You need to specify in a different way the moment in which this program has to finish, probably indicating the day and the hour like in this example: $NAME_PROGRAM \"2009/12/30 10:57\"."
fi

sleep "$seconds"

# // End of file
Ariel
la source
Bonne solution, cependant, je pense que $ SECONDS est une chaîne, donc le code défensif devrait être quelque chose comme obtenir d'abord une sous-chaîne comme ceci SIGNCHAR=${SECONDS:0:1}et ensuite if [ "$SIGNCHAR" = "-" ]. Ça devrait le faire.
H2ONaCl
1

Vous pouvez calculer le nombre de secondes entre maintenant et l'heure de réveil et utiliser la commande 'sleep' existante.

Programmeur hors-la-loi
la source
1

Vous pourriez peut-être utiliser «at» pour envoyer un signal à votre script, qui attendait ce signal.

Kim Reece
la source
Aww mec, j'écrivais juste une autre réponse à cet effet.
SpoonMeiser
Eh bien, en fait, non, le mien était légèrement différent.
SpoonMeiser
0

Voici quelque chose que j'ai écrit tout à l'heure pour synchroniser plusieurs clients de test:

#!/usr/bin/python
import time
import sys

now = time.time()
mod = float(sys.argv[1])
until = now - now % mod + mod
print "sleeping until", until

while True:
    delta = until - time.time()
    if delta <= 0:
        print "done sleeping ", time.time()
        break
    time.sleep(delta / 2)

Ce script dort jusqu'au prochain moment "arrondi" ou "pointu".

Un cas d'utilisation simple consiste à exécuter ./sleep.py 10; ./test_client1.pydans un terminal et ./sleep.py 10; ./test_client2.pydans un autre.

Dima Tisnek
la source
Où est le lien avec ma question?
theomega
il est facile de le prolonger pour qu'il untilsoit réglé à une date / heure spécifique
Dima Tisnek
0
 function sleepuntil() {
  local target_time="$1"
  today=$(date +"%m/%d/%Y")
  current_epoch=$(date +%s)
  target_epoch=$(date -d "$today $target_time" +%s)
  sleep_seconds=$(( $target_epoch - $current_epoch ))

  sleep $sleep_seconds
}

target_time="11:59"; sleepuntil $target_time
Nick Constantine
la source
Pouvez-vous ajouter une sorte de description à cette solution?
cdomination le
ceci est un script bash; la fonction sleepuntil prend un argument; vous définissez la variable target_time = "11:59" ou l'heure à laquelle vous voulez dormir jusqu'à; puis vous appelez la fonction avec l'argument target_time. Il calcule le nombre de secondes avant cette heure cible et dort pendant ce nombre de secondes
Nick Constantine
0

J'ai mis en place un petit utilitaire appelé Hypnos pour ce faire. Il est configuré à l'aide de la syntaxe crontab et des blocs jusqu'à ce moment-là.

#!/bin/bash
while [ 1 ]; do
  hypnos "0 * * * *"
  echo "running some tasks..."
  # ...
done
Kris Foster
la source
0

Pour étendre la réponse principale, voici quelques exemples valides concernant la manipulation de la chaîne de date:

sleep $(($(date -f - +%s- <<< $'+3 seconds\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'3 seconds\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'3 second\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'+2 minute\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'tomorrow\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'tomorrow 21:30\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'3 weeks\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'3 week\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'next Friday 09:00\nnow')0)) && ls

sleep $(($(date -f - +%s- <<< $'2027-01-01 00:00:01 UTC +5 hours\nnow')0)) && ls
NVRM
la source
-1

Sur OpenBSD , les éléments suivants peuvent être utilisés pour compacter un travail de */55 minutes crontab(5)en un travail 00horaire (pour s'assurer que moins d'e-mails sont générés, tout en effectuant la même tâche à des intervalles exacts):

#!/bin/sh -x
for k in $(jot 12 00 55)
  do
  echo $(date) doing stuff
  sleep $(expr $(date -j +%s $(printf %02d $(expr $k + 5))) - $(date -j +%s))
done

Notez que date(1)cela briserait également la sleep(1)conception lors de l'itération finale, car les 60minutes ne sont pas une heure valide (sauf si c'est le cas!), Nous n'aurons donc pas à attendre plus longtemps avant de recevoir notre rapport par courrier électronique.

Notez également que si l'une des itérations prend plus de 5 minutes qui lui sont allouées, le sleep cela échouerait également gracieusement par conception en ne dormant pas du tout (en raison de ce qui est un nombre négatif interprété comme une option de ligne de commande, au lieu de revenir à l'heure suivante ou même l'éternité), garantissant ainsi que votre travail puisse encore se terminer dans l'heure allouée (par exemple, si une seule des itérations prend un peu plus de 5 minutes, nous aurions encore le temps de rattraper le retard, sans quoi que ce soit qui s'enroule jusqu'à l'heure suivante).

Le printf(1)est nécessaire car dateattend exactement deux chiffres pour la spécification des minutes.

cnst
la source
-2

Utilisez du temps. C'est un outil que j'ai écrit pour le faire spécifiquement.

https://github.com/metaphyze/tarry/

Il s'agit d'un simple outil de ligne de commande pour attendre un moment précis. Ce n'est pas la même chose que «dormir» qui attendra un certain temps. Ceci est utile si vous voulez exécuter quelque chose à un moment précis ou plus probablement exécuter plusieurs choses exactement en même temps, comme tester si un serveur peut gérer plusieurs requêtes très simultanées. Vous pouvez l'utiliser comme ceci avec "&&" sous Linux, Mac ou Windows:

   tarry -until=16:03:04 && someOtherCommand

Cela attendrait jusqu'à 4:03:04 PM, puis exécuterait someOtherCommand. Voici un exemple Linux / Mac de la façon d'exécuter plusieurs requêtes planifiées pour démarrer en même temps:

   for request in 1 2 3 4 5 6 7 8 9 10
   do
       tarry -until=16:03:04 && date > results.$request &
   done

Les binaires Ubuntu, Linux et Windows sont disponibles via des liens sur la page.

métaphyser
la source