Pergunta

Pergunta

Pergunta

Eu gostaria de poder executar um comando UNIXprecisamentetodo segundodurante um longo período de tempo.

Preciso de uma solução que não fique para trás depois de um certo tempo, por causa do tempo que o próprio comando precisa para ser executado.dormir,assistir, e um certoscript pythontodos falharam comigo nesse aspecto.

Nos microcontroladores como ohttp://Arduino.ccEu faria isso através de interrupções de clock de hardware. Gostaria de saber se existe uma solução semelhante de script de shell com precisão de tempo. Todas as soluções que encontrei no StackExchange.com resultaram em um atraso de tempo perceptível, se executadas por horas. Veja os detalhes abaixo.

Finalidade prática/aplicação

Quero testar se minha conexão de rede está continuamente ativa enviando carimbos de data/hora via nc(netcat) a cada 1 segundo.

Remetente:

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

Receptor:

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

Após a conclusão, compare os dois logs:

diff netcat-sender.txt netcat-receiver.txt

As diferenças seriam os carimbos de data/hora não transmitidos. A partir disso eu saberia a que horas minha LAN/WAN/ISP apresenta problemas.


Solução SONO

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

Obtém um certo deslocamento ao longo do tempo, pois o comando dentro do loop também demora um pouco.

Precisão

cat timelog-sleep.txt

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

Segundos decorridos: 34520

wc -l timelog-sleep.txt

Linhas no arquivo: 34243

Precisão resumida:

  • 34520-34243 = 277 problemas de tempo
  • 34520/34243 = 1,008 = 0,8% de desconto

Solução REPETIR PYTHON

Encontrado em:Repita um comando Unix a cada x segundos para sempre

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

Supõe-se que evite o deslocamento de tempo, mas não o faz.

Precisão

wc -l timelog-repeat-py.txt

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

Segundos decorridos: 10960

wc -l timelog-repeat-py.txt

Linhas no arquivo: 10859

Precisão resumida:

  • 10960-10859 = 101 problemas de temporização
  • 10960/10859 = 1,009 = 0,9% de desconto

Solução ASSISTA

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

Precisão

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

Segundos decorridos: 8499

wc -l timelog-watch.txt

Linhas no arquivo: 8366

Precisão resumida:

  • 8499-8366 = 133 problemas de temporização.
  • 8499/8366 = 1,016 = 1,6% de desconto.

Responder1

Você já tentou watchcom o parâmetro --precise?

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

Na página de manual:

Normalmente, esse intervalo é interpretado como o tempo entre a conclusão de uma execução de comando e o início da próxima execução. No entanto, com a opção -p ou --precise, você pode fazer uma tentativa de observação para executar o comando a cada intervalo de segundos. Experimente com ntptime e observe como os segundos fracionários permanecem (quase) iguais, ao contrário do modo normal, onde aumentam continuamente.

No entanto, o parâmetro pode não estar disponível em seu sistema.

Você também deve considerar o que deve acontecer quando a execução do seu programa precisar de mais de um segundo. A próxima execução agendada deve ser ignorada ou atrasada?

Atualizar: Executei o script por algum tempo e ele não perdeu uma única etapa:

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

Atualizar:A --precisebandeira é uma adição do Debian, mas o patch é bastante simples:http://patch-tracker.debian.org/patch/series/view/procps/1:3.2.8-9squeeze1/watch_precision_time.patch

Responder2

O POSIXualarm()A função permite agendar o kernel para sinalizar periodicamente seu processo, com precisão de microssegundos.

Prepare um programa simples:

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

Compilar

 gcc -O2 tick.c -o tick

Em seguida, anexe-o a tudo o que você precisa fazer periodicamente, assim:

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

Responder3

crontabtem resolução de 1 minuto. Se você concordar com o tempo de atraso acumulado naquele minuto e redefinido no minuto seguinte, esta ideia básica pode funcionar:

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

Observe que script.shtambém é executado em segundo plano. Isso deve ajudar a minimizar o atraso acumulado a cada iteração do loop.

Dependendo de quanto atraso sleepé gerado, existe, no entanto, a chance do segundo 59 se sobrepor ao segundo 0 do minuto seguinte.

EDITARlançar alguns resultados, no mesmo formato da pergunta:

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

1 hora e 52 minutos = 6720 segundos

$ wc -l timelog-cron
6720 timelog-cron

0 problemas de tempo, 0% de desconto. Qualquer acumulação de tempo é reiniciada a cada minuto.

Responder4

Como funciona esse script Perl que acabei de criar?

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

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

Ele está funcionando há 45 minutos sem um único salto, e suspeito que continuará assim, a menos que a) a carga do sistema fique tão alta que fork() demore mais de um segundo ou b) um segundo bissexto seja inserido.

Ele não pode garantir, entretanto, que o comando seja executado em intervalos exatos de segundos, pois há alguma sobrecarga, mas duvido que seja muito pior do que uma solução baseada em interrupções.

Executei-o por cerca de uma hora com date +%N(nanossegundos, extensão GNU) e executei algumas estatísticas sobre ele. O maior atraso que teve foi de 1.155 microssegundos. Média (média aritmética) 216 µs, mediana 219 µs, desvio padrão 42 µs. Ele funcionou mais rápido que 270 µs em 95% do tempo. Eu não acho que você possa vencê-lo, exceto por um programa C.

informação relacionada