我希望能够在很长一段时间内精确地每秒运行一个 UNIX 命令。
我需要一个解决方案,它在一段时间后不会落后,因为命令本身需要执行时间。sleep,watch和某个python 脚本在这方面都让我失望。
在诸如http://Arduino.cc之类的微控制器上,我会通过硬件时钟中断来做到这一点。我想知道是否有类似的时间精确的shell脚本解决方案。我在 StackExchange.com 中找到的所有解决方案,如果运行超过几个小时,都会导致明显的时间延迟。请参阅下面的详细信息。
我想通过nc每 1 秒通过(netcat)发送时间戳来测试我的网络连接是否持续连接。
发件人:
precise-timestamp-generator | tee netcat-sender.txt | nc $receiver $port
Run Code Online (Sandbox Code Playgroud)
接收者:
nc -l -p $port > netcat-receiver.txt
Run Code Online (Sandbox Code Playgroud)
完成后,比较两个日志:
diff netcat-sender.txt netcat-receiver.txt
Run Code Online (Sandbox Code Playgroud)
差异将是未传输的时间戳。由此我可以知道我的 LAN / WAN / ISP 什么时候出问题。
while [ true ]; do date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done | tee timelog-sleep.txt
Run Code Online (Sandbox Code Playgroud)
随着时间的推移获得一定的偏移量,因为循环中的命令也需要一点时间。
cat timelog-sleep.txt
2012-07-16 00:45:16
[...]
2012-07-16 10:20:36
Run Code Online (Sandbox Code Playgroud)
经过的秒数:34520
wc -l timelog-sleep.txt
Run Code Online (Sandbox Code Playgroud)
文件中的行:34243
精度总结:
repeat.py 1 "date '+%Y-%m-%d %H:%M:%S'" >> timelog-repeat-py.txt
Run Code Online (Sandbox Code Playgroud)
应该避免时间偏移,但没有这样做。
wc -l timelog-repeat-py.txt
2012-07-16 13:42:44
[...]
2012-07-16 16:45:24
Run Code Online (Sandbox Code Playgroud)
经过的秒数:10960
wc -l timelog-repeat-py.txt
Run Code Online (Sandbox Code Playgroud)
文件中的行数:10859
精度总结:
watch -n 1 "date '+%Y-%m-%d %H:%M:%S' >> ~/Desktop/timelog-watch.txt"
Run Code Online (Sandbox Code Playgroud)
wc -l timelog-watch.txt
2012-07-16 11:04:08
[...]
2012-07-16 13:25:47
Run Code Online (Sandbox Code Playgroud)
经过的秒数:8499
wc -l timelog-watch.txt
Run Code Online (Sandbox Code Playgroud)
文件中的行数:8366
精度总结:
Dav*_*ave 29
POSIXualarm()函数允许您安排内核以微秒精度定期向您的进程发送信号。
编写一个简单的程序:
#include<unistd.h>
#include<signal.h>
void tick(int sig){
write(1, "\n", 1);
}
int main(){
signal(SIGALRM, tick);
ualarm(1000000, 1000000); //alarm in a second, and every second after that.
for(;;)
pause();
}
Run Code Online (Sandbox Code Playgroud)
编译
gcc -O2 tick.c -o tick
Run Code Online (Sandbox Code Playgroud)
然后将它附加到您需要定期完成的任何事情上,如下所示:
./tick | while read x; do
date "+%Y-%m-%d %H:%M:%S"
done | tee timelog-sleep.txt
Run Code Online (Sandbox Code Playgroud)
dan*_*ann 29
你试过watch参数--precise吗?
watch -n 1 --precise "date '+%Y-%m-%d %H:%M:%S.%N' >> ~/Desktop/timelog-watch.txt"
Run Code Online (Sandbox Code Playgroud)
从手册页:
通常,此间隔被解释为完成一次命令运行和下一次运行开始之间的时间量。但是,使用 -p 或 --precise 选项,您可以让 watch 尝试每隔 interval 秒运行一次命令。尝试使用 ntptime 并注意小数秒如何保持(几乎)相同,而不是它们持续增加的正常模式。
但是,该参数可能在您的系统上不可用。
您还应该考虑当您的程序执行需要超过一秒钟时会发生什么。应该跳过下一个预定的执行,还是应该延迟运行?
更新:我运行了一段时间脚本,它没有丢失任何一步:
2561 lines
start: 2012-07-17 09:46:34.938805108
end: 2012-07-17 10:29:14.938547796
Run Code Online (Sandbox Code Playgroud)
更新:该--precise标志是 Debian 添加的,但补丁相当简单:http : //patch-tracker.debian.org/patch/series/view/procps/1 : 3.2.8-9squeeze1/watch_precision_time.patch
Izk*_*ata 19
crontab分辨率为 1 分钟。如果您对每分钟累积的延迟时间感到满意,然后在下一分钟重置,那么这个基本想法可能会奏效:
* * * * * for second in $(seq 0 59); do /path/to/script.sh & sleep 1s;done
Run Code Online (Sandbox Code Playgroud)
请注意,script.sh它也在后台运行。这应该有助于最小化循环每次迭代累积的滞后。
sleep然而,根据产生的滞后量,第 59 秒有可能与下一分钟的第 0 秒重叠。
编辑以与问题中相同的格式抛出一些结果:
$ cat timelog-cron
2012-07-16 20:51:01
...
2012-07-16 22:43:00
Run Code Online (Sandbox Code Playgroud)
1 小时 52 分 = 6720 秒
$ wc -l timelog-cron
6720 timelog-cron
Run Code Online (Sandbox Code Playgroud)
0 时间问题,0% 折扣。任何时间累积每分钟重置一次。
hha*_*amu 12
我刚刚编写的这个 Perl 脚本是如何工作的?
#!/usr/bin/perl
use strict;
use warnings;
use Time::HiRes qw/time sleep/;
sub launch {
return if fork;
exec @_;
die "Couldn't exec";
}
$SIG{CHLD} = 'IGNORE';
my $interval = shift;
my $start = time();
while (1) {
launch(@ARGV);
$start += $interval;
sleep $start - time();
}
Run Code Online (Sandbox Code Playgroud)
用: perl timer.pl 1 date '+%Y-%m-%d %H:%M:%S'
它已经运行了 45 分钟而没有一次跳过,我怀疑它会继续这样做,除非 a) 系统负载变得如此之高以至于 fork() 需要超过一秒或 b) 插入闰秒。
然而,它不能保证命令以精确的秒间隔运行,因为有一些开销,但我怀疑它比基于中断的解决方案差得多。
我用date +%N(纳秒,GNU 扩展)运行了大约一个小时,并对其进行了一些统计。它的最大延迟是 1155 微秒。平均值(算术平均值)216 µs,中位数 219 µs,标准偏差 42 µs。它在 95% 的时间内运行速度超过 270 µs。我认为除非通过 C 程序,您无法击败它。
我总是放弃让某些东西完全按间隔运行。我认为您必须编写一个 C 程序,并非常小心地注意不要使用自己的代码超过 1 秒间隔的部分。您可能必须使用线程或多个相互通信的进程才能使其工作。注意避免线程启动或进程启动时间开销。
一个似乎与 1993 年相关的参考资料:用于 CPU 利用率估计和代码分析的随机采样时钟 您需要查看附录“对手源代码”,了解他们如何准确测量时间间隔,并“唤醒”他们的节目正好在正确的时间。由于代码已有 19 年的历史,因此可能无法直接或轻松移植,但如果您阅读并尝试理解它,所涉及的原则可能会指导您的代码。
编辑:找到另一个可能有帮助的参考资料:时钟分辨率对交互式和软实时进程的调度的影响, 这应该可以帮助您了解任何理论背景。
| 归档时间: |
|
| 查看次数: |
10728 次 |
| 最近记录: |