我要求如何等待下一秒?我不是说睡1! 例如,我们有时间07:45:06.729。 最后的729表示毫秒。 那我们怎么能说等到下一整秒?这将是07:45:07.000
谢谢;)
答案 0 :(得分:2)
这就像马特的回答,但没有忙碌等待试图提前醒来。这简化了 lot 的事情,因为除了当前时间的小数部分之外,我们从不关心任何事情。
使用GNU date +%N
获取当前时间的纳秒部分,使用sleep
获得1 - 。
sleep_to_next_second(){
sleep 0.$(printf '%04d' $((10000 - 10#$(date +%4N))))
}
技巧是:
带有前导零的数字在bash算术上下文中被视为八进制,因此请使用10#$date
到force base10。
由于bash只能进行整数数学运算,显而易见的是使用定点千分之一秒或者其他东西,然后使用前导小数点。这使得前导零必不可少,因此您可以睡眠0.092秒,而不是0.92。我使用printf '%04d'
来格式化我的数字。
实验测试:
# echo instead of sleep to see what numbers we generate
while true;do echo 0.$(printf '%04d' $((10000 - 10#$(date +%4N))));done
...
0.0049
0.0035
0.0015
0.10000 ##### minor bug: sleeps for 0.1 sec if the time was bang-on a ten-thousandth
0.9987
0.9973
0.9960
while true;do date +"%s %N"; sleep 0.$(printf '%04d' $((10000 - 10#$(date +%4N))));done
1445301422 583340443
1445301423 003697512
1445301424 003506054
1445301425 003266620
1445301426 003776955
1445301427 003921242
1445301428 003018890
1445301429 002652820
# So typical accuracy is 0.003 secs after the rollover to the next second, on a near-idle desktop
Ubuntu 15.04:GNU bash / date / sleep on Linux 3.19 on Intel i5-2500k,空闲时间为1.6GHz,turbo 3.8GHz。
答案 1 :(得分:1)
GNU sleep命令接受浮点参数。 因此,您可以计算等待的确切时间并使用结果调用睡眠。
请参阅https://superuser.com/questions/222301/unix-sleep-until-the-specified-time
和https://serverfault.com/questions/469247/how-do-i-sleep-for-a-millisecond-in-bash-or-ksh
答案 2 :(得分:1)
这更像是一个计时器解决方案。
它需要GNU date
,它可以用%N
和sleep
做纳秒,可以做小数,这是GNU做的,有些是做的。
您的里程数会因负载很重的系统而异。如果必须,这将跳过秒。
如果加载系统的准确性不那么重要,那么safety
可以更低(或者只使用Peter更简单的解决方案)。您使用的处理器时间越长,但它在高负载系统上准时的可能性略高。过了一点,你只是在浪费cpu时间。即使这样,如果你的系统有更好的安排,这将等待。
# ms to spend busy waiting * 10
safety=100
while true; do
if [ "$(date +%s)" != "$last_sec" ]; then
# Do whatever you need to here
date +"%S.%N"
# Then figure out how much to sleep until just
# before the next second.
sec_ns="$(date +"%s %4N")"
sec=${sec_ns:0:-5}
ms=${sec_ns:11}
last_sec=$sec
let sleep=10000-10#$ms-$safety
sleep 0.$(printf '%04d' $sleep)
fi
done
对date
和sleep
的调用是外部二进制文件,因此执行它们会有一些开销。正如评论中所提到的,bash可能不是这项工作的最佳工具。
另请注意,由于使用了子串,这将在11月20日星期六17:46:39 UTC 2286之后失败。希望我们的计算机领主在那时已经从他们的操作系统中删除了bash。谢谢你毁了我的笑话彼得=)
同时运行
[vagrant@localhost ~]$ /tmp/wait_seconds.sh
32.376187825
33.002727030
34.001005707
35.001850686
36.002232134
37.001802235
^C
[vagrant@localhost ~]$ while sleep 0.$(printf '%04d' $((10000 - 10#$(date +%4N) - 1))); do date +"%S.%N"; done
41.006809812
42.005389515
43.005793726
44.004930099
45.004829293
46.005988337
答案 3 :(得分:0)
使用bash
sleep echo "scale=3; $((1000 -$(echo $(cut -d '.' -f2 <<< "07:45:06.729"))))/1000"|bc
让我分解一下,因为它令人困惑
$(cut -d '.' -f2 <<< "07:45:06.729")
#这将获得毫秒部分
在上面的命令行上构建
echo "scale=3; $((1000 -$(echo $(cut -d '.' -f2 <<< "07:45:06.729"))))/1000"|bc
#这会给你分数
此后将剩余部分传递给sleep
编辑:使用较短的bash代码
答案 4 :(得分:0)
上面的答案是非常聪明的BASH,但最终我一直遇到奇怪的边缘问题试图只在BASH中这样做,所以我写了一个简单的C程序,而不是每次都很完美,并且非常简单易懂。
// Wait until the next second rolls over
// Use sleep rather than polling
#include <unistd.h>
#include <sys/time.h>
int main(void) {
unsigned int microseconds;
struct timeval tv;
gettimeofday(&tv, NULL);
// Calculate time until next round second...
microseconds = 1000000 - (tv.tv_usec);
usleep(microseconds);
return(0);
}
https://github.com/bigjosh/De-Harak-Clock-Controller/blob/master/nextsecond.c
使用命令构建实用程序...
gcc nextsecond.c
chmod +x nextsecond
您可以通过运行来测试它的工作原理......
./nextsecond; date "+%N"
它将打印自上一轮秒以来的纳秒数,该值应始终小于010000000,即10,000,000ns,即10ms。
答案 5 :(得分:0)
一个简单的功能,没有任何魔法
function sleepUntilTheNextSecond() {
local currentTimeMilliseconds
currentTimeMilliseconds=$(date +%s%3N)
local currentTimeSeconds=$(( currentTimeMilliseconds / 1000 ))
local targetTimeMilliseconds=$(( (currentTimeSeconds + 1) * 1000 ))
local sleepMilliseconds=$(( targetTimeMilliseconds - currentTimeMilliseconds ))
if (( sleepMilliseconds > 1000 )); then
echo "Invalid sleepMilliseconds (> 1000): $sleepMilliseconds"
exit 1
fi
sleep "0.$sleepMilliseconds"
}
经过GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)