जैसा कि यह सवाल 4 साल पहले पूछा गया था, यह पहला हिस्सा पुराने बैश संस्करणों की चिंता करता है:
अंतिम संपादन: बुध अप्रैल २२ २०२०, १०:३० से १० बजे के बीच कुछ: ५५ (नमूने पढ़ने के लिए महत्वपूर्ण)
सामान्य विधि (बेकार कांटे से बचें!)
(नोट: इस विधि का उपयोग date -f
विच कोई पोसिक्स नहीं है और मैकओएस के तहत काम नहीं करते हैं! यदि मैक के तहत, मेरा शुद्ध गोटो हैदे घुमा केसमारोह )
कम करने के लिए forks
, date
दो बार चलने के बजाय , मैं इसका उपयोग करना पसंद करता हूं:
सरल शुरुआती नमूना
sleep $(($(date -f - +%s- <<< $'tomorrow 21:30\nnow')0))
जहां भविष्य में tomorrow 21:30
किसी भी प्रकार की तिथि और प्रारूप को पहचाना जा सकता है date
।
उच्च परिशुद्धता (नैनोसेक) के साथ
लगभग समान:
sleep $(bc <<<s$(date -f - +'t=%s.%N;' <<<$'07:00 tomorrow\nnow')'st-t')
अगली बार पहुँचना
यदि संभव हो तो आज अगलेHH:MM
अर्थ तक पहुँचने के लिए , कल यदि बहुत देर हो चुकी हो:
sleep $((($(date -f - +%s- <<<$'21:30 tomorrow\nnow')0)%86400))
इसके तहत काम करता है दे घुमा के, क्ष और अन्य आधुनिक गोले, लेकिन आपको उपयोग करना होगा:
sleep $(( ( $(printf 'tomorrow 21:30\nnow\n' | date -f - +%s-)0 )%86400 ))
के तहत हल्का तरह के गोलेएश या पानी का छींटा।
शुद्ध दे घुमा के रास्ता, कोई कांटा नहीं !!
MacOS के तहत परीक्षण किया गया!
मैंने एक दो छोटे कार्य लिखे : sleepUntil
औरsleepUntilHires
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)
बैश के नए संस्करणों के रूप में printf
, एचएच तक सोने के इस नए तरीके के लिए, तारीख को पुनः प्राप्त करने का एक विकल्प प्रदान करते हैं : एमएम व्हाईटआउट का उपयोग करके date
या किसी अन्य कांटा के साथ, मैंने थोड़ा सा निर्माण किया हैदे घुमा केसमारोह। यह रहा:
sleepUntil() {
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
}
फिर:
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
यदि लक्ष्य इससे पहले है तो कल तक सो जाएगा:
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 समय के साथ दे घुमा के GNU / Linux के तहत
हाल का दे घुमा के, संस्करण 5.0 से $EPOCHREALTIME
माइक्रोसेकंड के साथ नया चर जोड़ें । इससे एक sleepUntilHires
फंक्शन होता है।
sleepUntilHires () {
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
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
}
कृपया ध्यान दें: यह उपयोग read -t
विच-इन के बजाय अंतर्निहित है sleep
। दुर्भाग्य से, यह वास्तविक TTY के बिना, पृष्ठभूमि में चलने पर काम नहीं करेगा। बदलने के लिए स्वतंत्र महसूस read -t
द्वारा sleep
यदि आप ... (लेकिन पृष्ठभूमि प्रक्रिया के लिए उपयोग करने पर विचार पृष्ठभूमि स्क्रिप्ट में इस चलाना चाहते हैं cron
और / या at
बजाय सभी इस बात का)
परीक्षण और चेतावनी के बारे में अगले पैराग्राफ को छोड़ दें $ËPOCHSECONDS
!
हाल के कर्नेल /proc/timer_list
उपयोगकर्ता द्वारा उपयोग करने से बचें !!
हाल ही में लिनक्स कर्नेल के तहत, आपको एक वेरिएबल फ़ाइल मिलेगी, जिसका नाम `/ proc / टाइमर_लिस्ट` है, जहां आप ** नैनोसेकंड ** में एक` ऑफसेट` और `अब` वेरिएबल पढ़ सकते हैं। इसलिए हम सोने के समय की गणना * बहुत ऊपर * वांछित समय तक करने के लिए कर सकते हैं।
(मैंने इसे बहुत बड़ी लॉग फ़ाइलों पर विशिष्ट घटनाओं को उत्पन्न करने और ट्रैक करने के लिए लिखा था, जिसमें एक सेकंड के लिए हजार लाइन शामिल हैं)।
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
}
दो रीड-ओनली वेरिएबल्स को परिभाषित करने के बाद , TIMER_LIST_OFFSET
और TIMER_LIST_SKIP
, फ़ंक्शन बहुत ही जल्दी से /proc/timer_list
स्लीप टाइम की गणना के लिए वैरिएबल फ़ाइल तक पहुंच जाएगा :
थोड़ा परीक्षण समारोह
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
}
कुछ इस तरह प्रस्तुत करना:
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
- अगले सेकंड की शुरुआत में,
- प्रिंट समय, तब
- 0.92 सेकंड प्रतीक्षा करें, फिर
- प्रिंट समय, तब
- अगले सेकंड तक 0.07 सेकंड बचे
- नींद 0.07 सेकंड, फिर
- प्रिंट समय।
मिश्रण नहीं करने के लिए देखभाल $EPOCHSECOND
और $EPOCHREALTIME
!
और के बीच अंतर के बारे में मेरी चेतावनी पढ़ें$EPOCHSECOND
$EPOCHREALTIME
यह फ़ंक्शन उपयोग $EPOCHREALTIME
इसलिए अगले सेकंड की$EPOCHSECOND
स्थापना के लिए उपयोग न करें :
नमूना मुद्दा: अगले दौर को 2 सेकंड तक प्रिंट करने का प्रयास:
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
उत्पादन कर सकते हैं:
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