Ngủ cho đến một giờ / ngày cụ thể


89

Tôi muốn kịch bản bash của mình ngủ yên cho đến một thời điểm cụ thể. Vì vậy, tôi muốn một lệnh như "sleep" không mất khoảng thời gian mà là thời gian kết thúc và ngủ cho đến khi đó.

-Daemon "at" không phải là một giải pháp, vì tôi cần chặn một tập lệnh đang chạy cho đến một ngày / giờ nhất định.

Có lệnh như vậy không?


1
Lưu ý rằng giải pháp đơn giản chỉ sử dụng một chế độ ngủ dài trước khi tính toán có thể ngủ quá lâu, có thể quá lâu, đặc biệt nếu bạn có máy có thể chuyển sang chế độ ngủ đông. Lệnh ngủ posix không hứa hẹn về việc không ngủ quá lâu. Giải pháp của @Camusensei giải quyết mối quan tâm rất tốt.
GregD

Câu trả lời:


98

Như đã đề cập bởi Outlaw Programmer, tôi nghĩ rằng giải pháp chỉ là ngủ trong số giây chính xác.

Để làm điều này trong bash, hãy làm như sau:

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

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

sleep $sleep_seconds

Để thêm độ chính xác xuống nano giây (hiệu quả hơn khoảng mili giây), hãy sử dụng ví dụ: cú pháp sau:

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

Lưu ý rằng macOS / OS X không hỗ trợ độ chính xác dưới giây, bạn sẽ cần sử dụng coreutilstừ brewthay thế → xem các hướng dẫn này


8
Cảm ơn vì điều đó, tôi đã viết một shell-script nhỏ để nhận lệnh "sleepuntil".
theomega

1
@enigmaticPhysicist: Có một lệnh gọi tương tự "at", chạy không đồng bộ.
voidlogic

6
Nếu bạn muốn dừng lại lúc 3 giờ sáng ngày mai, bạn có thể sử dụng target_epoch=$(date -d 'tomorrow 03:00' +%s)thay thế.
Yajo

Bạn có thể làm tương tự bằng cách sử dụng một cái nĩa datethay vì hai cái! Xem phần 1 của câu trả lời của tôi
F. Hauri

1
Lưu ý rằng giải pháp này có thể ngủ quá lâu và nếu máy của bạn ở chế độ ngủ đông một chút, nó có thể quá lâu.
GregD

23

Như câu hỏi này đã được hỏi 4 năm trước, phần đầu tiên này liên quan đến phiên bản bash:

Chỉnh sửa lần cuối: Thứ 4 ngày 22 tháng 4 năm 2020, khoảng từ 10:30 đến 10h: 55 (Quan trọng đối với việc đọc mẫu)

Phương pháp chung (Tránh các ngã ba vô dụng!)

(Nota: đây sử dụng phương pháp date -f! Mà là không POSIX và không làm việc theo hệ điều hành MacOS Nếu dưới Mac, goto tôi tinh khiếtchức năng )

Để giảm forks, thay vì chạy datehai lần, tôi thích sử dụng điều này:

Mẫu bắt đầu đơn giản

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

nơi tomorrow 21:30có thể được thay thế bằng bất kỳ loại ngày tháng và định dạng nào được công nhận datetrong tương lai.

Với độ chính xác cao (nanosec)

Gần giống nhau:

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

Tiếp cận lần sau

Để đạt được ý nghĩa tiếp theoHH:MM ngày hôm nay nếu có thể, ngày mai nếu quá muộn:

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

Điều này hoạt động dưới , và các shell hiện đại khác, nhưng bạn phải sử dụng:

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

dưới lớp vỏ nhẹ hơn như hoặc là .

Nguyên chất cách, không có ngã ba !!

Đã thử nghiệm trên MacOS!

Tôi đã viết một trong hai hàm nhỏ: sleepUntilsleepUntilHires

 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)

Vì các phiên bản mới của bash cung cấp một printftùy chọn để truy xuất ngày, đối với cách mới này để ngủ cho đến khi HH: MM sử dụng datehoặc bất kỳ ngã ba nào khác, tôi đã xây dựng một chútchức năng. Nó đây:

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
}

Sau đó:

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

Nếu mục tiêu nằm trước mục tiêu này sẽ ngủ cho đến ngày mai:

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

HiRes thời gian với theo GNU / Linux

Gần đây , từ phiên bản 5.0 thêm $EPOCHREALTIMEbiến mới với micro giây. Từ đó có một sleepUntilHireschức năng.

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
}

Xin lưu ý: công cụ sử dụng read -tnày được tích hợp sẵn, thay vì sleep. Thật không may, điều này sẽ không hoạt động khi chạy trong nền, không có TTY thực. Vui lòng thay thế read -tbằng sleepnếu bạn định chạy điều này trong các tập lệnh nền ... (Nhưng đối với quy trình nền, hãy cân nhắc sử dụng cronvà / hoặc atthay vì tất cả điều này)

Bỏ qua đoạn tiếp theo để kiểm tra và cảnh báo về $ËPOCHSECONDS!

Kernel gần đây tránh /proc/timer_listđược người dùng sử dụng !!

Trong nhân Linux gần đây, bạn sẽ tìm thấy một tệp biến có tên `/ proc / timer_list`, nơi bạn có thể đọc một biến` offset` và một biến `now`, trong ** nano giây **. Vì vậy, chúng tôi có thể tính toán thời gian ngủ để đạt được thời gian * rất cao nhất * mong muốn.

(Tôi đã viết điều này để tạo và theo dõi các sự kiện cụ thể trên các tệp nhật ký rất lớn, chứa hàng nghìn dòng trong một giây).

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
}

Sau khi xác định hai biến chỉ đọcTIMER_LIST_OFFSETTIMER_LIST_SKIP, hàm sẽ truy cập rất nhanh vào tệp biến /proc/timer_listđể tính toán thời gian ngủ:

Chức năng kiểm tra nhỏ

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
}

Có thể hiển thị một cái gì đó như:

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
  • Vào đầu giây tiếp theo,
  • thời gian in, sau đó
  • đợi 0,92 giây, sau đó
  • thời gian in, sau đó
  • tính 0,07 giây còn lại, sang giây tiếp theo
  • ngủ 0,07 giây, sau đó
  • thời gian in.

Cẩn thận để không trộn lẫn $EPOCHSECOND$EPOCHREALTIME!

Đọc cảnh báo của tôi về sự khác biệt giữa $EPOCHSECOND$EPOCHREALTIME

Chức năng này sử dụng $EPOCHREALTIMEvì vậy không sử dụng $EPOCHSECONDđể thiết lập giây tiếp theo :

Vấn đề mẫu: Đang cố gắng in thời gian làm tròn 2 giây tiếp theo:

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

Có thể sản xuất:

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

1
Chà! Tính toán nano giây dưới bash !
F. Hauri

Tính toán micro giây dưới bash v5 + !!
F. Hauri

21

Sử dụng sleep, nhưng tính toán thời gian sử dụng date. Bạn sẽ muốn sử dụng date -dcho việc này. Ví dụ: giả sử bạn muốn đợi đến tuần sau:

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

Chỉ cần thay thế "tuần tới" bằng bất kỳ ngày nào bạn muốn chờ, sau đó gán biểu thức này cho một giá trị và ngủ trong nhiều giây đó:

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

Tất cả đã được làm xong!


Nó có giá trị mở rộng về cách bạn chỉ định giá trị cho một biến, vì timeToWait = expr ... sẽ không hoạt động trực tiếp và bạn không thể sử dụng backticks vì chúng sẽ không lồng vào nhau, vì vậy bạn sẽ phải sử dụng $ (), hoặc các biến tạm thời.
SpoonMeiser

Gợi ý tốt; Tôi sẽ sửa đổi của tôi để làm cho điều đó rõ ràng hơn để mọi người không hiểu sai.
John Feminella

Lưu ý -dlà tiện ích mở rộng không phải POSIX cho đến nay. Trên FreeBSD, nó cố gắng đặt giá trị của hạt nhân cho thời gian tiết kiệm ánh sáng ban ngày.
Dave C

9

Đây là một giải pháp thực hiện công việc VÀ thông báo cho người dùng về lượng thời gian còn lại. Tôi sử dụng nó hầu như hàng ngày để chạy các tập lệnh trong đêm (sử dụng cygwin, vì tôi không thể cronlàm việc trên windows)

Đặc trưng

  • Chính xác đến giây
  • Phát hiện các thay đổi và điều chỉnh thời gian của hệ thống
  • Đầu ra thông minh cho biết thời gian còn lại
  • Định dạng đầu vào 24 giờ
  • trả về true để có thể liên kết với &&

Chạy mẫu

$ 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

(Ngày ở cuối không phải là một phần của hàm, mà là do && date)

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
}

8

Bạn có thể ngăn một quá trình thực thi bằng cách gửi cho nó một tín hiệu SIGSTOP, sau đó để nó tiếp tục thực thi bằng cách gửi cho nó một tín hiệu SIGCONT.

Vì vậy, bạn có thể dừng tập lệnh của mình bằng cách gửi là một SIGSTOP:

kill -SIGSTOP <pid>

Và sau đó sử dụng at deamon để đánh thức nó bằng cách gửi nó một SIGCONT theo cách tương tự.

Có lẽ, kịch bản của bạn sẽ thông báo về thời điểm nó muốn được đánh thức trước khi đi vào giấc ngủ.


8

Trên Ubuntu 12.04.4 LTS, đây là đầu vào bash đơn giản hoạt động:

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

7

Để theo dõi câu trả lời của SpoonMeiser, đây là một ví dụ cụ thể:

$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
$

Tôi nghĩ bạn muốn lên lịch cho một SIGCONT chứ không phải một SIGSTOP khác, do đó, tín hiệu hoặc nhận xét là sai. Nếu không, rất vui được xem một ví dụ thích hợp.
SpoonMeiser

Rất tiếc, tôi đã đánh máy nhận xét. Hiện đã được sửa. Nhưng bạn phải xem bằng cách sử dụng các tín hiệu số, vì chúng có thể khác nhau.
Tạm dừng cho đến khi có thông báo mới.

Tôi thấy rằng dấu gạch ngang có vẻ không hiểu SIGCONT, vì vậy lúc đầu tôi sử dụng -18 là không di động, sau đó tôi thấy rằng nó thích CONT, vì vậy tôi đã chỉnh sửa câu trả lời ở trên để khắc phục điều đó.
Tạm dừng cho đến khi có thông báo mới.

6

Tôi muốn một tập lệnh chỉ kiểm tra giờ và phút để tôi có thể chạy tập lệnh với các thông số giống nhau mỗi ngày. Tôi không muốn lo lắng về ngày mai sẽ là ngày nào. Vì vậy, tôi đã sử dụng một cách tiếp cận khác.

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

các tham số cho tập lệnh là giờ và phút, vì vậy tôi có thể viết một cái gì đó như:

til 7 45 && mplayer song.ogg

(cho đến khi là tên của kịch bản)

không còn ngày nào đi làm muộn khiến bạn nhập nhầm ngày. chúc mừng!


4

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

Hãy lưu ý rằng "timeToWait" có thể là một số âm! (ví dụ: nếu bạn chỉ định ngủ cho đến "15:57" và bây giờ là "15:58"). Vì vậy, bạn phải kiểm tra nó để tránh lỗi thông báo lạ:

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

Giải pháp tốt, tuy nhiên, tôi nghĩ $ SECONDS là một chuỗi vì vậy mã phòng thủ phải là một cái gì đó giống như lấy một chuỗi con trước SIGNCHAR=${SECONDS:0:1}và sau đó if [ "$SIGNCHAR" = "-" ]. Nên làm vậy.
H2ONaCl


1

Có lẽ bạn có thể sử dụng 'at' để gửi tín hiệu đến tập lệnh của mình, tập lệnh đang chờ tín hiệu đó.


Ôi trời, tôi vừa viết ra một câu trả lời khác cho hiệu ứng này.
SpoonMeiser

Thực ra, không, của tôi hơi khác.
SpoonMeiser


0

Đây là nội dung tôi đã viết ngay bây giờ để đồng bộ hóa nhiều ứng dụng khách thử nghiệm:

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

Tập lệnh này sẽ ngủ cho đến thời điểm "làm tròn" hoặc "sắc nét" tiếp theo.

Một trường hợp sử dụng đơn giản là chạy ./sleep.py 10; ./test_client1.pytrong một thiết bị đầu cuối và ./sleep.py 10; ./test_client2.pytrong một thiết bị đầu cuối khác.


Kết nối với câu hỏi của tôi ở đâu?
theomega

thật dễ dàng để mở rộng do đó untilđược thiết lập để một ngày cụ thể / lần
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

Bạn có thể thêm một số loại mô tả cho giải pháp này?
cdomination

đây là một tập lệnh bash; hàm sleepuntil nhận một đối số; bạn đặt biến target_time = "11:59" hoặc bất kỳ thời gian nào bạn muốn ngủ; thì bạn gọi hàm với đối số target_time. Nó tính toán có bao nhiêu giây là đến thời gian đó mục tiêu và ngủ cho số tiền đó của giây
Nick Constantine

0

Tôi đã kết hợp một tiện ích nhỏ có tên là Hypnos để thực hiện việc này. Nó được cấu hình bằng cách sử dụng cú pháp crontab và các khối cho đến thời điểm đó.

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

0

Để mở rộng câu trả lời chính, đây là một số ví dụ hợp lệ về thao tác chuỗi ngày:

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

-1

Trên OpenBSD , những điều sau đây có thể được sử dụng để thu gọn một công việc */55 phút crontab(5)thành một công việc 00hàng giờ (để đảm bảo rằng ít email được tạo hơn, tất cả đều thực hiện cùng một tác vụ ở những khoảng thời gian chính xác):

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

Lưu ý rằng dấu date(1)cũng sẽ phá vỡ sleep(1)thiết kế trong lần lặp cuối cùng, vì 60phút không phải là thời gian hợp lệ (trừ khi đúng!), Do đó chúng tôi sẽ không phải đợi thêm thời gian trước khi nhận được báo cáo email của mình.

Cũng lưu ý rằng nếu một trong các lần lặp mất hơn 5 phút được phân bổ cho nó, sleeptương tự như vậy sẽ thất bại theo thiết kế bởi hoàn toàn không ngủ (do một số âm được hiểu là một tùy chọn dòng lệnh, thay vì quấn quanh để giờ tiếp theo hoặc thậm chí vĩnh viễn), do đó đảm bảo công việc của bạn vẫn có thể hoàn thành trong vòng giờ được phân bổ (ví dụ: nếu chỉ một trong các lần lặp mất hơn 5 phút một chút, thì chúng tôi vẫn có thời gian để bắt kịp, không cần bất cứ điều gì bao quanh đến giờ tiếp theo).

Điều printf(1)này là cần thiết vì datemong đợi chính xác hai chữ số cho đặc điểm kỹ thuật phút.


-2

Sử dụng hắc ín. Đó là một công cụ tôi đã viết để đặc biệt làm điều này.

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

Đây là một công cụ dòng lệnh đơn giản để chờ đợi cho đến một thời điểm cụ thể. Điều này không giống như "ngủ" sẽ đợi trong một khoảng thời gian. Điều này rất hữu ích nếu bạn muốn thực thi một thứ gì đó tại một thời điểm cụ thể hoặc nhiều khả năng thực thi nhiều thứ cùng lúc, chẳng hạn như kiểm tra xem máy chủ có thể xử lý nhiều yêu cầu đồng thời hay không. Bạn có thể sử dụng nó như thế này với "&&" trên Linux, Mac hoặc Windows:

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

Điều này sẽ đợi cho đến 4:03:04 PM và sau đó thực thi một số Lệnh khác. Dưới đây là một ví dụ Linux / Mac về cách chạy nhiều yêu cầu, tất cả được lập lịch để bắt đầu cùng một lúc:

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

Hệ nhị phân Ubuntu, Linux và Windows có sẵn thông qua các liên kết trên trang.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.