質問

質問

質問

UNIXコマンドを実行できるようにしたい正確に一秒ごと長期間にわたって

コマンド自体の実行には時間がかかるため、一定時間経過後に遅延が発生しないソリューションが必要です。寝る時計、そしてあるPython スクリプトこの点に関しては、すべてが失敗でした。

マイクロコントローラでは、http://Arduino.cc私はハードウェア クロック割り込みを使用してこれを実行します。同様の正確な時間を持つシェル スクリプト ソリューションがあるかどうか知りたいです。StackExchange.com 内で見つけたすべてのソリューションでは、数時間にわたって実行すると、顕著な時間差が生じます。詳細は以下を参照してください。

実用目的/用途

nc1 秒ごとに (netcat)経由でタイムスタンプを送信して、ネットワーク接続が継続的に稼働しているかどうかをテストします。

送信者:

precise-timestamp-generator | tee netcat-sender.txt | nc $receiver $port

受信者:

nc -l -p $port > netcat-receiver.txt

完了したら、2 つのログを比較します。

diff netcat-sender.txt netcat-receiver.txt

差分は、送信されなかったタイムスタンプになります。これにより、LAN / WAN / ISP に問題が発生した時刻がわかります。


ソリューション SLEEP

while [ true ]; do date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done | tee timelog-sleep.txt

ループ内のコマンドにも少し時間がかかるため、時間の経過とともに一定のオフセットが発生します。

精度

cat timelog-sleep.txt

2012-07-16 00:45:16
[...]
2012-07-16 10:20:36

経過秒数: 34520

wc -l timelog-sleep.txt

ファイル内の行数: 34243

精度の要約:

  • 34520-34243 = 277 タイミングの問題
  • 34520/34243 = 1.008 = 0.8 % オフ

ソリューション REPEAT PYTHON

見つかった場所:Unix コマンドを x 秒ごとに永久に繰り返す

repeat.py 1 "date '+%Y-%m-%d %H:%M:%S'" >> timelog-repeat-py.txt

時間オフセットを回避するはずでしたが、失敗しました。

精度

wc -l timelog-repeat-py.txt

2012-07-16 13:42:44
[...]
2012-07-16 16:45:24

経過秒数: 10960

wc -l timelog-repeat-py.txt

ファイル内の行数: 10859

精度の要約:

  • 10960-10859 = 101 タイミングの問題
  • 10960/10859 = 1.009 = 0.9 % オフ

ソリューションを見る

watch -n 1 "date '+%Y-%m-%d %H:%M:%S' >> ~/Desktop/timelog-watch.txt"

精度

wc -l timelog-watch.txt
2012-07-16 11:04:08
[...]
2012-07-16 13:25:47

経過秒数: 8499

wc -l timelog-watch.txt

ファイル内の行数: 8366

精度の要約:

  • 8499-8366 = 133 のタイミングの問題。
  • 8499/8366 = 1.016 = 1.6 % オフ。

答え1

watchパラメータを試しましたか--precise?

watch -n 1 --precise "date '+%Y-%m-%d %H:%M:%S.%N' >> ~/Desktop/timelog-watch.txt"

man ページから:

通常、この間隔は、コマンドの 1 回の実行が完了してから次の実行が開始されるまでの時間として解釈されます。ただし、-p または --precise オプションを使用すると、watch が interval 秒ごとにコマンドを実行しようと試みるようにすることができます。ntptime で試してみると、秒の小数部が (ほぼ) 同じままであることがわかります。通常モードでは秒の小数部が継続的に増加します。

ただし、このパラメータはシステム上で使用できない可能性があります。

プログラムの実行に 1 秒以上かかる場合に何が起こるかについても考慮する必要があります。次にスケジュールされている実行をスキップするべきでしょうか、それとも遅れて実行するべきでしょうか。

アップデート: しばらくスクリプトを実行しましたが、1 つのステップも失われませんでした。

2561 lines
start: 2012-07-17 09:46:34.938805108
end:   2012-07-17 10:29:14.938547796

アップデート:この--preciseフラグは Debian の追加機能ですが、パッチはかなりシンプルです。http://patch-tracker.debian.org/patch/series/view/procps/1:3.2.8-9squeeze1/watch_precision_time.patch

答え2

POSIXはualarm()関数を使用すると、カーネルがマイクロ秒の精度でプロセスに定期的に信号を送るようにスケジュールできます。

簡単なプログラムを作成します。

 #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();
 }

コンパイル

 gcc -O2 tick.c -o tick

次に、定期的に実行する必要があるものに次のように添付します。

./tick | while read x; do
    date "+%Y-%m-%d %H:%M:%S"
done | tee timelog-sleep.txt

答え3

crontab解像度は 1 分です。1 分ごとに遅延時間が蓄積され、次の 1 分でリセットされることに問題がない場合は、次の基本的なアイデアが役立ちます。

* * * * * for second in $(seq 0 59); do /path/to/script.sh & sleep 1s;done

バックグラウンドでも実行されることに注意してくださいscript.sh。これにより、ループの各反復で蓄積される遅延を最小限に抑えることができます。

ただし、発生するラグの量によってはsleep、59 秒が次の 1 分間の 0 秒と重なる可能性があります。

編集質問と同じ形式で、いくつかの結果を入力します。

$ cat timelog-cron
2012-07-16 20:51:01
...
2012-07-16 22:43:00

1時間52分 = 6720秒

$ wc -l timelog-cron
6720 timelog-cron

タイミングの問題は 0 件、割引率は 0% です。時間の累積は 1 分ごとにリセットされます。

答え4

今作ったこの 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();
}

使用:perl timer.pl 1 date '+%Y-%m-%d %H:%M:%S'

45 分間、一度もスキップすることなく実行されており、(a) システム負荷が非常に高くなって fork() に 1 秒以上かかるか、(b) うるう秒が挿入されない限り、この状態が続くと思われます。

ただし、オーバーヘッドがあるため、コマンドが正確に 1 秒間隔で実行されることを保証することはできませんが、割り込みベースのソリューションよりもはるかに悪いとは思いません。

私はこれを (ナノ秒、GNU 拡張) で約 1 時間実行しdate +%N、統計をいくつか実行しました。最大の遅延は 1,155 マイクロ秒でした。平均 (算術平均) 216 µs、中央値 219 µs、標準偏差 42 µs。95% の時間で 270 µs より速く実行されました。C プログラム以外ではこれを上回ることはできないと思います。

関連情報