Duerme hasta una fecha / hora específica

89

Quiero que mi script de bash duerma hasta una hora específica. Entonces, quiero un comando como "dormir" que no toma un intervalo sino una hora de finalización y duerme hasta entonces.

El "at" -daemon no es una solución, ya que necesito bloquear un script en ejecución hasta una determinada fecha / hora.

¿Existe tal comando?

theomega
fuente
1
Tenga en cuenta que la solución que simplemente usa una suspensión prolongada precedida de un cálculo puede dormir demasiado, tal vez demasiado, especialmente si tiene una máquina que puede hibernar. El comando posix sleep no promete no dormir demasiado. La solución de @Camusensei aborda la preocupación muy bien.
GregD

Respuestas:

98

Como lo mencionó Outlaw Programmer, creo que la solución es simplemente dormir el número correcto de segundos.

Para hacer esto en bash, haga lo siguiente:

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

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

sleep $sleep_seconds

Para agregar precisión hasta nanosegundos (efectivamente más alrededor de milisegundos) use, por ejemplo, esta sintaxis:

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

Tenga en cuenta que macOS / OS X no admite precisión por debajo de los segundos, necesitaría usar coreutilsde en su brewlugar → consulte estas instrucciones

SpoonMeiser
fuente
8
Gracias por eso, escribí un pequeño script de shell para obtener un comando "sleepuntil".
theomega
1
@enigmaticPhysicist: Hay una llamada de comando similar "at", que se ejecuta de forma asíncrona.
voidlogic
6
Si desea detenerse mañana a las 3 a. M., Puede usar target_epoch=$(date -d 'tomorrow 03:00' +%s)en su lugar.
Yajo
¡Podrías hacer lo mismo usando una bifurcación en datelugar de dos! Vea la primera parte de mi respuesta
F. Hauri
1
Tenga en cuenta que esta solución puede dormir demasiado tiempo, y si su máquina hiberna un poco, puede ser demasiado tiempo.
GregD
23

Como esta pregunta se hizo hace 4 años, esta primera parte se refiere a versiones antiguas de bash:

Última edición: miércoles 22 de abril de 2020, algo entre las 10:30 y las 10h: 55 (importante para las muestras de lectura)

Método general (¡Evite los tenedores inútiles!)

(Nota: este uso del método date -f! Wich hay POSIX y no hacer el trabajo bajo MacOS Si en Mac, ir a mi purafunción )

Para reducir forks, en lugar de ejecutar datedos veces, prefiero usar esto:

Muestra inicial simple

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

donde tomorrow 21:30podría ser reemplazado por cualquier tipo de fecha y formato reconocido por date, en el futuro.

Con alta precisión (nanosec)

Casi lo mismo:

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

Alcanzando la próxima vez

Para alcanzar el siguienteHH:MM significado hoy si es posible, mañana si es demasiado tarde:

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

Esto funciona bajo , y otras carcasas modernas, pero debes usar:

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

bajo conchas más ligeras como o .

Puro camino, sin tenedor !!

¡Probado en MacOS!

Escribí uno de dos pequeñas funciones: sleepUntilysleepUntilHires

 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)

Como las nuevas versiones de bash ofrecen una printfopción para recuperar la fecha, para esta nueva forma de dormir hasta HH: MM sin usar dateo cualquier otra bifurcación, he construido un pocofunción. Aquí está:

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
}

Entonces:

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 el objetivo es antes, este dormirá hasta mañana:

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

Hola tiempo con bajo GNU / Linux

Reciente , a partir de la versión 5.0 agregue una nueva $EPOCHREALTIMEvariable con microsegundos. De esto hay una sleepUntilHiresfunción.

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
}

Tenga en cuenta: este uso read -testá integrado, en lugar de sleep. Desafortunadamente, esto no funcionará cuando se ejecute en segundo plano, sin TTY real. Siéntase libre de reemplazar read -tpor sleepsi planea ejecutar esto en scripts en segundo plano ... (Pero para el proceso en segundo plano, considere usar crony / o en atlugar de todo esto)

Omita el siguiente párrafo para las pruebas y advertencias $ËPOCHSECONDS.

¡El kernel reciente evita el uso /proc/timer_listpor parte del usuario!

Bajo el reciente kernel de Linux, encontrará un archivo de variables llamado `/ proc / timer_list` donde puede leer un` offset` y una variable `now`, en ** nanosegundos **. Por lo tanto, podemos calcular el tiempo de sueño para alcanzar el * máximo * tiempo deseado.

(Escribí esto para generar y rastrear eventos específicos en archivos de registro muy grandes, que contienen mil líneas por un segundo).

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
}

Después de definir dos variables de solo lectura , TIMER_LIST_OFFSETy TIMER_LIST_SKIP, la función accederá muy rápidamente al archivo de variables /proc/timer_listpara calcular el tiempo de suspensión:

Pequeña función de prueba

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
}

Puede representar algo como:

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
  • Al comienzo del siguiente segundo,
  • tiempo de impresión, entonces
  • espere 0.92 segundos, luego
  • tiempo de impresión, entonces
  • calcular 0.07 segundos restantes, al siguiente segundo
  • dormir 0.07 segundos, luego
  • tiempo de impresión.

¡Cuidado de no mezclar $EPOCHSECONDy $EPOCHREALTIME!

Lea mi advertencia sobre la diferencia entre $EPOCHSECONDy$EPOCHREALTIME

Esta función se usa, $EPOCHREALTIMEasí que no la use $EPOCHSECONDpara establecer el siguiente segundo :

Problema de muestra: Intentando imprimir el tiempo siguiente redondeado en 2 segundos:

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

Puede producir:

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
fuente
1
¡Guauu! ¡Calcular nanosegundos bajo bash !
F. Hauri
Cálculo de microsegundos bajo nativa bash v5 + !!
F. Hauri
21

Use sleep, pero calcule el tiempo usando date. Querrás usarlo date -dpara esto. Por ejemplo, digamos que desea esperar hasta la próxima semana:

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

Simplemente sustituya "la próxima semana" con la fecha que le gustaría esperar, luego asigne esta expresión a un valor y duerma durante tantos segundos:

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

¡Todo listo!

John Feminella
fuente
Vale la pena expandir sobre cómo asignaría el valor a una variable, ya que timeToWait = expr ... no funcionará directamente, y no puede usar comillas invertidas porque no anidan, por lo que tendrá que usar $ () o variables temporales.
SpoonMeiser
Buena sugerencia; Modificaré el mío para que quede más claro para que la gente no se haga una idea equivocada.
John Feminella
Note -des una extensión que no es POSIX hasta la fecha. En FreeBSD, intenta establecer el valor del kernel para el horario de verano.
Dave C
9

Aquí hay una solución que hace el trabajo E informa al usuario sobre cuánto tiempo queda. Lo uso casi todos los días para ejecutar scripts durante la noche (usando cygwin, ya que no pude crontrabajar en Windows)

Caracteristicas

  • Preciso hasta el segundo
  • Detecta cambios de hora del sistema y se adapta
  • Salida inteligente que indica cuánto tiempo queda
  • Formato de entrada de 24 horas
  • devuelve verdadero para poder encadenar con &&

Ejecución de muestra

$ 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 fecha al final no es parte de la función, sino debido a && date)

Código

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
fuente
8

Puede detener la ejecución de un proceso enviándole una señal SIGSTOP y luego hacer que reanude la ejecución enviándole una señal SIGCONT.

Para que pueda detener su script enviando un SIGSTOP:

kill -SIGSTOP <pid>

Y luego usa el at deamon para despertarlo enviándole un SIGCONT de la misma manera.

Es de suponer que su guión le informará cuándo desea que lo despierten antes de ponerse a dormir.

SpoonMeiser
fuente
8

En Ubuntu 12.04.4 LTS, aquí está la entrada bash simple que funciona:

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

Para seguir la respuesta de SpoonMeiser, aquí hay un ejemplo específico:

$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
$
Pausado hasta nuevo aviso.
fuente
Creo que desea programar un SIGCONT, en lugar de otro SIGSTOP, por lo que la señal o el comentario son incorrectos. De lo contrario, es bueno ver un ejemplo adecuado.
SpoonMeiser
Vaya, escribí el comentario. Ahora arreglado. Pero tienes que mirar usando señales numéricas, ya que pueden ser diferentes.
Pausado hasta nuevo aviso.
Descubrí que el tablero parece no entender SIGCONT, así que al principio usé -18, que no es portátil, luego descubrí que le gusta CONT, así que edité la respuesta anterior para solucionarlo.
Pausado hasta nuevo aviso.
6

Quería un script que solo verificara las horas y los minutos para poder ejecutar el script con los mismos parámetros todos los días. No quiero preocuparme de qué día será mañana. Entonces usé un enfoque diferente.

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

los parámetros del script son las horas y los minutos, así que puedo escribir algo como:

til 7 45 && mplayer song.ogg

(hasta que es el nombre del guión)

no más días tarde en el trabajo porque escribiste mal el día. ¡salud!

Kolomer
fuente
4

timeToWait = $ (($ final - $ inicio))

¡Tenga en cuenta que "timeToWait" podría ser un número negativo! (por ejemplo, si especifica dormir hasta las "15:57" y ahora son las "15:58"). Así que tienes que comprobarlo para evitar errores de mensajes extraños:

#!/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
fuente
Buena solución, sin embargo, creo que $ SECONDS es una cadena, por lo que el código defensivo debería ser algo así como obtener una subcadena primero así SIGNCHAR=${SECONDS:0:1}y luego if [ "$SIGNCHAR" = "-" ]. Deberias hacer eso.
H2ONaCl
1

Puede calcular el número de segundos entre ahora y la hora del despertador y utilizar el comando "dormir" existente.

Programador fuera de la ley
fuente
1

Quizás podría usar 'at' para enviar una señal a su guión, que estaba esperando esa señal.

Kim Reece
fuente
Aww hombre, solo estaba escribiendo otra respuesta en este sentido.
SpoonMeiser
Bueno, en realidad, no, el mío era un poco diferente.
SpoonMeiser
0

Aquí hay algo que escribí hace un momento para sincronizar varios clientes de prueba:

#!/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)

Este guión permanece inactivo hasta el próximo momento "redondeado" o "puntual".

Un caso de uso simple es ejecutar ./sleep.py 10; ./test_client1.pyen una terminal y ./sleep.py 10; ./test_client2.pyen otra.

Dima Tisnek
fuente
¿Dónde está la conexión con mi pregunta?
theomega
es fácil de extender para que untilse establezca en una fecha / hora específica
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
fuente
¿Puede agregar algún tipo de descripción a esta solución?
dominación
este es un script bash; función dormir hasta que toma un argumento; estableces la variable target_time = "11:59" o la hora que quieras dormir hasta; luego llamas a la función con el argumento target_time. Calcula cuántos segundos faltan para ese tiempo objetivo y duerme esa cantidad de segundos
Nick Constantine
0

Reuní una pequeña utilidad llamada Hypnos para hacer esto. Se configura usando la sintaxis crontab y se bloquea hasta ese momento.

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

Para extender la respuesta principal, aquí hay algunos ejemplos válidos con respecto a la manipulación de la cadena de fecha:

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
fuente
-1

En OpenBSD , lo siguiente podría usarse para compactar un trabajo de */55 minutos crontab(5)en 00uno por hora (para asegurarse de que se generen menos correos electrónicos, todo mientras se realiza la misma tarea en intervalos exactos):

#!/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

Tenga en cuenta que date(1)también rompería el sleep(1)diseño en la iteración final, ya que los 60minutos no son un tiempo válido (¡a menos que lo sea!), Por lo que no tendremos que esperar más tiempo antes de recibir nuestro informe por correo electrónico.

También tenga en cuenta que si una de las iteraciones toma más de 5 minutos asignados, el sleepdiseño también fallaría gentilmente al no dormir en absoluto (debido a lo que es un número negativo interpretado como una opción de línea de comandos, en lugar de ajustarse a la próxima hora o incluso la eternidad), asegurándonos así de que su trabajo podría completarse dentro de la hora asignada (por ejemplo, si solo una de las iteraciones toma un poco más de 5 minutos, entonces aún tendríamos tiempo para ponernos al día, sin cualquier cosa que envuelva a la próxima hora).

Se printf(1)necesita porque dateespera exactamente dos dígitos para la especificación de minutos.

cnst
fuente
-2

Utilice alquitrán. Es una herramienta que escribí para hacer esto específicamente.

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

Esta es una herramienta de línea de comandos simple para esperar hasta una hora específica. Esto no es lo mismo que "dormir", que esperará durante un tiempo. Esto es útil si desea ejecutar algo en un momento específico o, más probablemente, ejecutar varias cosas exactamente al mismo tiempo, como probar si un servidor puede manejar múltiples solicitudes muy simultáneas. Puede usarlo así con "&&" en Linux, Mac o Windows:

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

Esto esperaría hasta las 4:03:04 PM y luego ejecutaría someOtherCommand. Aquí hay un ejemplo de Linux / Mac de cómo ejecutar varias solicitudes, todas programadas para iniciarse al mismo tiempo:

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

Los binarios de Ubuntu, Linux y Windows están disponibles a través de enlaces en la página.

metafisis
fuente