Запуск петли именно один раз в секунду

Найдите параметр httpProxy в / etc / sysconfig / rhn / up2date !

33
07.08.2018, 14:04
6 ответов

Чтобы быть ближе к исходному коду, я делаю следующее:

while true; do
  sleep 1 &
 ...your stuff here...
  wait # for sleep
done

Это немного меняет семантику. :Если ваш материал занял меньше секунды, он просто будет ждать, пока не пройдет целая секунда. Однако, если ваш материал по какой-либо причине занимает больше секунды, он не будет порождать еще больше подпроцессов без конца.

Таким образом, ваши вещи никогда не работают параллельно и не в фоновом режиме, поэтому переменные тоже работают должным образом.

Обратите внимание, что если вы также запускаете дополнительные фоновые задачи, вам придется изменить инструкцию wait, чтобы она ждала только процесса sleep.

Если вам нужно, чтобы он был еще более точным, вам, вероятно, придется просто синхронизировать его с системными часами и спать мс вместо полных секунд.


Как синхронизировать системные часы? Понятия не имею, глупая попытка:

По умолчанию:

while sleep 1
do
    date +%N
done

Выход :003511461 010510925 016081282 021643477 028504349 03...(продолжает расти)

Синхронизировано:

 while sleep 0.$((1999999999 - 1$(date +%N)))
 do
     date +%N
 done

Выход :002648691 001098397 002514348 001293023 001679137 00... (остается прежним)

67
27.01.2020, 19:37

У меня было точно такое же требование для сценария оболочки POSIX, где все помощники (usleep, GNUsleep, sleepenh,... )недоступны.

см.:https://stackoverflow.com/a/54494216

#!/bin/sh

get_up()
{
        read -r UP REST </proc/uptime
        export UP=${UP%.*}${UP#*.}
}

wait_till_1sec_is_full()
{
    while true; do
        get_up
        test $((UP-START)) -ge 100 && break
    done
}

while true; do
    get_up; START=$UP

    your_code

    wait_till_1sec_is_full
done
1
27.01.2020, 19:37

Выполнение операций в подоболочке, работающей как фоновое задание, не будет так сильно мешать sleep.

while true; do
  (
    TIME=$(date +%T)
    # some calculations which take a few hundred milliseconds
    FOO=...
    BAR=...
    printf '%s  %s  %s\n' "$TIME" "$FOO" "$BAR"
  ) &
  sleep 1
done

Единственным временем, «украденным» из одной секунды, будет время, необходимое для запуска подоболочки, поэтому в конечном итоге она будет пропускать секунду, но, надеюсь, реже, чем исходный код.

Если код в подоболочке в конечном итоге использует больше секунды, цикл начнет накапливать фоновые задания и в конечном итоге исчерпает ресурсы.

11
27.01.2020, 19:37

Если вы можете реструктурировать свой цикл в скрипт/oneliner, то проще всего это сделать с помощьюwatchи его опции precise.

Вы можете увидеть эффект с помощью watch -n 1 sleep 0.5-: секунды будут показывать вверх, но иногда будут пропускаться секунды. Запуск его как watch -n 1 -p sleep 0.5будет выводить два раза в секунду, каждую секунду, и вы не увидите никаких пропусков.

30
27.01.2020, 19:37

Сzsh:

n=0
typeset -F SECONDS=0
while true; do
  date '+%FT%T.%2N%z'
  ((++n > SECONDS)) && sleep $((n - SECONDS))
done

Если ваш сон не поддерживает секунды с плавающей запятой, вы можете использовать zsh's zselectвместо (послеzmodload zsh/zselect):

zmodload zsh/zselect
n=0
typeset -F SECONDS=0
while true; do
  date '+%FZ%T.%2N%z'
  ((++n > SECONDS)) && zselect -t $((((n - SECONDS) * 100) | 0))
done

Они не должны дрейфовать, пока команды в цикле выполняются менее одной секунды.

7
27.01.2020, 19:37

Другая альтернатива (, если вы не можете использовать, например, watch -p, как предлагает Maelstrom ), это sleepenh[ справочная страница ], которая предназначена для это.

Пример:

#!/bin/sh

t=$(sleepenh 0)
while true; do
        date +'sec=%s ns=%N'
        sleep 0.2
        t=$(sleepenh $t 1)
done

Обратите внимание на sleep 0.2там, где симуляция выполняет некоторое время, -задача потребляет около 200 мс. Несмотря на это, выход в наносекундах остается стабильным (ну, по стандартам ОС, не -реального времени )— это происходит раз в секунду:

sec=1533663406 ns=840039402
sec=1533663407 ns=840105387
sec=1533663408 ns=840380678
sec=1533663409 ns=840175397
sec=1533663410 ns=840132883
sec=1533663411 ns=840263150
sec=1533663412 ns=840246082
sec=1533663413 ns=840259567
sec=1533663414 ns=840066687

Отличия менее 1 мс, тренда нет. Это очень хорошо; вы должны ожидать отскока не менее 10 мс, если есть какая-либо нагрузка на систему, но при этом не происходит дрейфа с течением времени. То есть вы не потеряете ни секунды.

9
27.01.2020, 19:37

Теги

Похожие вопросы