Tidur sampai waktu / tanggal tertentu

92

Saya ingin skrip bash saya tertidur sampai waktu tertentu. Jadi, saya ingin perintah seperti "tidur" yang tidak memerlukan jeda kecuali waktu berakhir dan tidur sampai saat itu.

The "at" -daemon bukanlah solusi, karena saya perlu memblokir skrip yang sedang berjalan hingga tanggal / waktu tertentu.

Apakah ada perintah seperti itu?

theomega
sumber
1
Perhatikan bahwa solusi yang hanya menggunakan tidur lama yang didahului dengan perhitungan mungkin tidur terlalu lama, mungkin terlalu lama terutama jika Anda memiliki mesin yang dapat hibernasi. Perintah tidur posix tidak berjanji untuk tidak tidur terlalu lama. Solusi oleh @Camusensei mengatasi masalah tersebut dengan sangat baik.
GregD

Jawaban:

101

Seperti yang disebutkan oleh Outlaw Programmer, menurut saya solusinya adalah tidur selama beberapa detik yang benar.

Untuk melakukan ini di bash, lakukan hal berikut:

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

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

sleep $sleep_seconds

Untuk menambahkan presisi hingga nanodetik (efektif lebih sekitar milidetik) gunakan misalnya sintaks ini:

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

Perhatikan bahwa macOS / OS X tidak mendukung presisi di bawah detik, Anda harus menggunakan coreutilsfrom brewlihat instruksi ini

SpoonMeiser
sumber
8
Terima kasih untuk itu, saya menulis skrip shell kecil untuk mendapatkan perintah "sleepuntil".
theomega
1
@enigmaticPhysicist: Ada panggilan perintah serupa "at", yang menjalankan async.
voidlogic
8
Jika Anda ingin berhenti besok jam 3 pagi, Anda bisa menggunakan target_epoch=$(date -d 'tomorrow 03:00' +%s).
Yajo
Anda dapat melakukan hal yang sama dengan menggunakan satu garpu, datebukan dua! Lihat bagian pertama dari jawaban saya
F. Hauri
1
Perhatikan bahwa solusi ini berpotensi tidur terlalu lama, dan jika mesin Anda sedikit hibernasi, bisa jadi terlalu lama.
GregD
26

Karena pertanyaan ini diajukan 4 tahun yang lalu, bagian pertama ini menyangkut versi bash lama :

Edit terakhir: Rabu, 22 Apr 2020, antara pukul 10.30 dan 10.00: 55 (Penting untuk membaca sampel)

Metode umum (Hindari garpu yang tidak berguna!)

(Catatan: metode ini menggunakan date -fyang bukan POSIX dan tidak berfungsi di MacOS! Jika di bawah Mac, goto my purefungsi )

Untuk mengurangi forks, daripada menjalankan datedua kali, saya lebih suka menggunakan ini:

Sampel awal yang sederhana

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

di mana tomorrow 21:30dapat diganti dengan segala jenis tanggal dan format yang dikenali date, di masa mendatang.

Dengan presisi tinggi (nanosec)

Hampir sama:

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

Mencapai lain kali

Untuk mencapai makna selanjutnyaHH:MM hari ini jika memungkinkan, besok jika terlambat:

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

Ini bekerja di bawah , dan cangkang modern lainnya, tetapi Anda harus menggunakan:

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

di bawah cangkang yang lebih ringan seperti atau .

Murni jalan, tidak ada garpu !!

Diuji di bawah MacOS!

Saya menulis satu dua fungsi kecil: sleepUntildansleepUntilHires

 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)

Karena versi baru bash menawarkan printfopsi untuk mengambil tanggal, untuk cara baru tidur ini hingga HH: MM tanpa menggunakan dateatau garpu lain, saya telah membangun sedikitfungsi. Ini dia:

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
}

Kemudian:

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

Jika target sebelum ini akan tidur sampai besok:

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

Waktu HiRes dengan di bawah GNU / Linux

Baru , dari versi 5.0 tambahkan $EPOCHREALTIMEvariabel baru dengan mikrodetik. Dari sini ada sleepUntilHiresfungsi.

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
}

Harap dicatat: penggunaan ini read -tyang sudah built-in, bukan sleep. Sayangnya, ini tidak akan berfungsi saat berjalan di latar belakang, tanpa TTY asli. Jangan ragu untuk mengganti read -tdengan sleepjika Anda berencana untuk menjalankan ini di skrip latar belakang ... (Tetapi untuk proses latar belakang, pertimbangkan untuk menggunakan crondan / atau atalih-alih semua ini)

Lewati paragraf berikutnya untuk tes dan peringatan tentang $ËPOCHSECONDS!

Kernel terbaru menghindari penggunaan /proc/timer_listoleh pengguna !!

Di bawah kernel Linux terbaru, Anda akan menemukan file variabel bernama `/ proc / timer_list` di mana Anda dapat membaca variabel` offset` dan `now`, dalam ** nanodetik **. Jadi, kami dapat menghitung waktu tidur untuk mencapai waktu * paling atas * yang diinginkan.

(Saya menulis ini untuk menghasilkan dan melacak peristiwa tertentu pada file log yang sangat besar, berisi ribuan baris untuk satu detik).

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
}

Setelah menentukan dua variabel hanya-baca , TIMER_LIST_OFFSETdan TIMER_LIST_SKIP, fungsi tersebut akan mengakses dengan sangat cepat file variabel /proc/timer_listuntuk menghitung waktu tidur:

Fungsi tes kecil

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
}

Mungkin membuat sesuatu seperti:

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
  • Di awal detik berikutnya,
  • mencetak waktu, lalu
  • tunggu 0,92 detik, lalu
  • mencetak waktu, lalu
  • hitung 0,07 detik tersisa, ke detik berikutnya
  • tidur 0,07 detik, lalu
  • waktu cetak.

Peduli untuk tidak mencampur $EPOCHSECONDdan $EPOCHREALTIME!

Baca peringatan saya tentang perbedaan antara $EPOCHSECONDdan$EPOCHREALTIME

Fungsi ini digunakan $EPOCHREALTIMEjadi jangan gunakan $EPOCHSECONDuntuk menetapkan detik berikutnya :

Contoh masalah: Mencoba mencetak waktu berikutnya dibulatkan oleh 2 detik:

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

Dapat menghasilkan:

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
sumber
1
Wow! Menghitung nanodetik di bawah bash !
F. Hauri
Menghitung detik mikro di bawah native bash v5 + !!
F. Hauri
Catatan Pedantic: %86400trik ini hanya bekerja jika dua waktu tidak menjangkau transisi waktu musim panas.
200_success
@ 200_success Anda dapat menerapkan offset waktu: Cari tzoffdi jawaban saya!
F. Hauri
21

Gunakan sleep, tapi hitung waktu menggunakan date. Anda akan ingin menggunakan date -duntuk ini. Misalnya, Anda ingin menunggu hingga minggu depan:

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

Cukup gantikan "minggu depan" dengan tanggal berapa pun yang ingin Anda tunggu, lalu tetapkan ekspresi ini ke nilai, dan tidur selama beberapa detik itu:

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

Semua selesai!

John Feminella
sumber
Ada baiknya memperluas cara Anda menetapkan nilai ke variabel, karena timeToWait = expr ... tidak akan berfungsi secara langsung, dan Anda tidak dapat menggunakan backticks karena tidak akan bersarang, jadi Anda harus menggunakan $ (), atau variabel sementara.
SpoonMeiser
Saran yang bagus; Saya akan memodifikasi milik saya untuk membuatnya lebih jelas sehingga orang tidak salah paham.
John Feminella
Note -dadalah ekstensi non-POSIX hingga saat ini. Di FreeBSD mencoba untuk mengatur nilai kernel untuk waktu musim panas.
Dave C
9

Berikut adalah solusi yang melakukan pekerjaan DAN memberi tahu pengguna tentang berapa banyak waktu yang tersisa. Saya menggunakannya hampir setiap hari untuk menjalankan skrip pada malam hari (menggunakan cygwin, karena saya tidak bisa cronbekerja di windows)

fitur

  • Tepat sampai yang kedua
  • Mendeteksi perubahan waktu sistem dan beradaptasi
  • Output cerdas memberi tahu berapa banyak waktu yang tersisa
  • Format masukan 24 jam
  • mengembalikan true agar dapat dirantai &&

Contoh dijalankan

$ 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

(Tanggal di akhir bukanlah bagian dari fungsi, tetapi karena && date)

Kode

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

Anda dapat menghentikan proses dari eksekusi, dengan mengirimkannya sinyal SIGSTOP, dan kemudian membuatnya melanjutkan eksekusi dengan mengirimkannya sinyal SIGCONT.

Jadi Anda bisa menghentikan skrip Anda dengan mengirimkan SIGSTOP:

kill -SIGSTOP <pid>

Dan kemudian gunakan at deamon untuk membangunkannya dengan mengirimkannya SIGCONT dengan cara yang sama.

Agaknya, skrip Anda akan memberi tahu kapan ia ingin dibangunkan sebelum tidur.

SpoonMeiser
sumber
8

Di Ubuntu 12.04.4 LTS, berikut adalah input bash sederhana yang berfungsi:

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

Untuk mengikuti jawaban SpoonMeiser, berikut adalah contoh spesifiknya:

$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
$
Dennis Williamson
sumber
Saya pikir Anda ingin menjadwalkan SIGCONT, daripada SIGSTOP lain, jadi mungkin sinyalnya, atau komentarnya salah. Jika tidak, senang melihat contoh yang tepat.
SpoonMeiser
Ups, saya salah ketik komentarnya. Sekarang sudah diperbaiki. Tetapi Anda harus memperhatikan dengan menggunakan sinyal numerik, karena bisa berbeda.
Dennis Williamson
Saya menemukan bahwa dasbor sepertinya tidak mengerti SIGCONT, jadi awalnya saya menggunakan -18 yang tidak portabel, kemudian saya menemukan bahwa itu menyukai CONT, jadi saya mengedit jawaban di atas untuk memperbaikinya.
Dennis Williamson
6

Saya menginginkan skrip yang hanya memeriksa jam dan menit sehingga saya dapat menjalankan skrip dengan parameter yang sama setiap hari. Saya tidak ingin khawatir tentang hari apa besok. Jadi saya menggunakan pendekatan yang berbeda.

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

parameter pada skrip adalah jam dan menit, jadi saya bisa menulis sesuatu seperti:

til 7 45 && mplayer song.ogg

(til adalah nama skrip)

tidak ada lagi hari terlambat di tempat kerja karena Anda salah mengetik hari itu. Bersulang!

kolomer
sumber
4

timeToWait = $ (($ akhir - $ mulai))

Berhati-hatilah karena "timeToWait" bisa berupa angka negatif! (misalnya, jika Anda menetapkan untuk tidur sampai "15:57" dan sekarang "15:58"). Jadi Anda harus memeriksanya untuk menghindari kesalahan pesan aneh:

#!/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
sumber
Solusi yang baik, bagaimanapun, saya pikir $ DETIK adalah string sehingga kode pertahanan harus seperti mendapatkan substring terlebih dahulu seperti ini SIGNCHAR=${SECONDS:0:1}dan kemudian if [ "$SIGNCHAR" = "-" ]. Itu harus dilakukan.
H2ONaCl
1

Anda dapat menghitung jumlah detik antara sekarang dan waktu bangun dan menggunakan perintah 'tidur' yang ada.

Programmer Penjahat
sumber
1

Anda mungkin dapat menggunakan 'at' untuk mengirim sinyal ke skrip Anda, yang menunggu sinyal itu.

Kim Reece
sumber
Aduh, saya baru saja menulis jawaban lain untuk efek ini.
SpoonMeiser
Sebenarnya, tidak, milikku sedikit berbeda.
SpoonMeiser
0

Inilah yang baru saja saya tulis untuk menyinkronkan beberapa klien uji:

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

Skrip ini tidur sampai waktu "bulat" atau "tajam" berikutnya.

Contoh penggunaan sederhana adalah menjalankan ./sleep.py 10; ./test_client1.pydi satu terminal dan ./sleep.py 10; ./test_client2.pydi terminal lain.

Dima Tisnek
sumber
Dimana hubungannya dengan pertanyaan saya?
theomega
mudah untuk diperpanjang sehingga untildiatur ke tanggal / waktu tertentu
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
sumber
Dapatkah Anda menambahkan semacam deskripsi ke solusi ini?
dominasi
ini adalah skrip bash; fungsi sleepuntil mengambil satu argumen; Anda menyetel variabel target_time = "11:59" atau jam berapa pun Anda ingin tidur sampai; lalu Anda memanggil fungsi tersebut dengan argumen target_time. Ini menghitung berapa detik hingga waktu target itu dan tidur selama jumlah detik itu
Nick Constantine
0

Saya mengumpulkan utilitas kecil yang disebut Hypnos untuk melakukan ini. Ini dikonfigurasi menggunakan sintaks crontab dan blok sampai saat itu.

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

Untuk memperluas jawaban utama, berikut adalah beberapa contoh valid mengenai manipulasi string tanggal:

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

Di OpenBSD , berikut ini dapat digunakan untuk memadatkan pekerjaan */55 menit crontab(5)menjadi satu 00jam (untuk memastikan lebih sedikit email yang dibuat, semuanya sambil melakukan tugas yang sama dengan interval yang tepat):

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

Perhatikan bahwa date(1)itu juga akan merusak sleep(1)by design pada iterasi terakhir, seperti60 menit bukanlah waktu yang valid (kecuali jika memang demikian!), Jadi kita tidak perlu menunggu waktu tambahan sebelum mendapatkan laporan email kita.

Perhatikan juga bahwa jika salah satu iterasi membutuhkan waktu lebih dari 5 menit yang dialokasikan untuk itu, file sleep itu juga akan dengan anggun gagal dengan desain dengan tidak tidur sama sekali (karena apa angka negatif ditafsirkan sebagai opsi baris perintah, alih-alih membungkus sekitar ke satu jam ke depan atau bahkan keabadian), sehingga memastikan pekerjaan Anda masih dapat diselesaikan dalam waktu yang ditentukan (misalnya, jika hanya satu pengulangan yang membutuhkan waktu lebih dari 5 menit, maka kami masih memiliki waktu untuk menyusul, tanpa apa pun yang membungkus hingga satu jam berikutnya).

Ini printf(1)diperlukan karena datemengharapkan tepat dua digit untuk spesifikasi menit.

cnst
sumber
-2

Gunakan tinggal. Ini adalah alat yang saya tulis khusus untuk melakukan ini.

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

Ini adalah alat baris perintah sederhana untuk menunggu hingga waktu tertentu. Ini tidak sama dengan "tidur" yang menunggu dalam jangka waktu tertentu. Ini berguna jika Anda ingin menjalankan sesuatu pada waktu tertentu atau lebih mungkin mengeksekusi beberapa hal pada waktu yang sama persis seperti menguji apakah server dapat menangani beberapa permintaan yang sangat bersamaan. Anda dapat menggunakannya seperti ini dengan "&&" di Linux, Mac, atau Windows:

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

Ini akan menunggu sampai 4:03:04 dan kemudian menjalankan someOtherCommand. Berikut adalah contoh Linux / Mac tentang cara menjalankan beberapa permintaan yang semuanya dijadwalkan untuk dimulai pada waktu yang sama:

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

Biner Ubuntu, Linux, dan Windows tersedia melalui tautan di halaman.

metafisis
sumber