Frage

Frage

Frage

Ich möchte einen UNIX-Befehl ausführen könnengenaujede Sekundeüber einen langen Zeitraum.

Ich brauche eine Lösung, die nicht nach einer gewissen Zeit ins Hintertreffen gerät, weil der Befehl selbst Zeit für die Ausführung braucht.schlafen,betrachtenund eine gewissePython-Skriptalle haben mich in dieser Hinsicht im Stich gelassen.

Auf den Mikrocontrollern wie demhttp://Arduino.ccIch würde das über Hardware-Uhr-Interrupts tun. Ich würde gerne wissen, ob es eine ähnliche zeitgenaue Shell-Skript-Lösung gibt. Alle Lösungen, die ich bei StackExchange.com gefunden habe, führten zu einer merklichen Zeitverzögerung, wenn sie über Stunden ausgeführt wurden. Siehe Details unten.

Praktischer Zweck / Anwendung

Ich möchte testen, ob meine Netzwerkverbindung kontinuierlich aktiv ist, indem ich ncalle Sekunde Zeitstempel über (netcat) sende.

Absender:

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

Empfänger:

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

Vergleichen Sie nach Abschluss die beiden Protokolle:

diff netcat-sender.txt netcat-receiver.txt

Die Differenzen wären die nicht übertragenen Zeitstempel. Daraus wüsste ich, zu welcher Zeit mein LAN / WAN / ISP Probleme macht.


Lösung SLEEP

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

Bekommt mit der Zeit einen gewissen Versatz, da der Befehl innerhalb der Schleife auch etwas Zeit braucht.

Präzision

cat timelog-sleep.txt

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

Verstrichene Sekunden: 34520

wc -l timelog-sleep.txt

Zeilen in der Datei: 34243

Präzision zusammengefasst:

  • 34520-34243 = 277 Timingprobleme
  • 34520/34243 = 1,008 = 0,8 % Rabatt

Lösung REPEAT PYTHON

Gefunden am:Wiederholen Sie einen Unix-Befehl alle x Sekunden für immer

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

Soll den Zeitversatz vermeiden, gelingt aber nicht.

Präzision

wc -l timelog-repeat-py.txt

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

Verstrichene Sekunden: 10960

wc -l timelog-repeat-py.txt

Zeilen in der Datei: 10859

Präzision zusammengefasst:

  • 10960-10859 = 101 Timingprobleme
  • 10960/10859 = 1,009 = 0,9 % Rabatt

Lösung ANSEHEN

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

Präzision

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

Verstrichene Sekunden: 8499

wc -l timelog-watch.txt

Zeilen in der Datei: 8366

Präzision zusammengefasst:

  • 8499-8366 = 133 Timingprobleme.
  • 8499/8366 = 1,016 = 1,6 % Rabatt.

Antwort1

Haben Sie es watchmit dem Parameter versucht --precise?

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

Aus der Manpage:

Normalerweise wird dieses Intervall als die Zeitspanne zwischen der Beendigung eines Befehlslaufs und dem Beginn des nächsten Laufs interpretiert. Mit der Option -p oder --precise können Sie jedoch dafür sorgen, dass watch alle Intervallsekunden versucht, den Befehl auszuführen. Probieren Sie es mit ntptime aus und beachten Sie, dass die Sekundenbruchteile (fast) gleich bleiben, im Gegensatz zum normalen Modus, wo sie kontinuierlich zunehmen.

Der Parameter ist auf Ihrem System jedoch möglicherweise nicht verfügbar.

Sie sollten auch überlegen, was passieren soll, wenn die Ausführung Ihres Programms länger als eine Sekunde dauert. Soll die nächste geplante Ausführung übersprungen oder verspätet ausgeführt werden?

Aktualisieren: Ich habe das Skript eine Zeit lang ausgeführt und es hat keinen einzigen Schritt verloren:

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

Aktualisieren:Das --preciseFlag ist eine Debian-Ergänzung, der Patch ist jedoch ziemlich einfach:http://patch-tracker.debian.org/patch/series/view/procps/1:3.2.8-9squeeze1/watch_precision_time.patch

Antwort2

Der POSIXualarm()Mit dieser Funktion können Sie den Kernel so planen, dass er Ihrem Prozess regelmäßig Signale mit einer Genauigkeit im Mikrosekundenbereich sendet.

Erstellen Sie ein einfaches Programm:

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

Kompilieren

 gcc -O2 tick.c -o tick

Hängen Sie es dann an die Dinge an, die Sie regelmäßig erledigen müssen, und zwar folgendermaßen:

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

Antwort3

crontabhat eine Auflösung von 1 Minute. Wenn Sie damit einverstanden sind, dass sich die Verzögerungszeit pro Minute ansammelt und dann in der nächsten Minute zurückgesetzt wird, könnte diese Grundidee funktionieren:

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

Beachten Sie, dass script.shes auch im Hintergrund ausgeführt wird. Dies sollte dazu beitragen, die Verzögerung zu minimieren, die bei jeder Iteration der Schleife auftritt.

Abhängig von der Größe der sleepauftretenden Verzögerung besteht jedoch die Möglichkeit, dass sich Sekunde 59 mit Sekunde 0 der nächsten Minute überschneidet.

BEARBEITENum einige Ergebnisse im gleichen Format wie in der Frage einzufügen:

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

1 Stunde 52 Minuten = 6720 Sekunden

$ wc -l timelog-cron
6720 timelog-cron

0 Zeitprobleme, 0 % Rabatt. Jede Zeitakkumulation wird jede Minute zurückgesetzt.

Antwort4

Wie funktioniert dieses Perl-Skript, das ich gerade zusammengebastelt habe?

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

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

Es läuft seit 45 Minuten ohne eine einzige Unterbrechung und ich vermute, dass dies auch so bleiben wird, es sei denn, a) die Systemlast wird so hoch, dass fork() länger als eine Sekunde dauert oder b) es wird eine Schaltsekunde eingefügt.

Es kann allerdings nicht garantiert werden, dass der Befehl im Sekundentakt ausgeführt wird, da ein gewisser Overhead entsteht, aber ich bezweifle, dass es viel schlechter ist als eine unterbrechungsbasierte Lösung.

Ich habe es etwa eine Stunde lang mit date +%N(Nanosekunden, GNU-Erweiterung) laufen lassen und einige Statistiken dazu erstellt. Die größte Verzögerung betrug 1.155 Mikrosekunden. Durchschnitt (arithmetisches Mittel) 216 µs, Median 219 µs, Standardabweichung 42 µs. 95 % der Zeit lief es schneller als 270 µs. Ich glaube nicht, dass man es schlagen kann, außer mit einem C-Programm.

verwandte Informationen