Повторять команду Unix каждые x секунд навсегда

Существует встроенная команда Unix repeat, первым аргументом которой является количество повторений команды, где команда (с любыми аргументами) указана оставшимися аргументами в repeat.

Например,

% repeat 100 echo "I will not automate this punishment."

будет повторять данную строку 100 раз, а затем останавливаться.

Мне нужна аналогичная команда - назовем ее forever â € ", которая работает аналогично, кроме первого аргумента, - это количество секунд для паузы между повторами, и оно повторяется навсегда. Например,

% forever 5 echo "This will get echoed every 5 seconds forever and ever."

Я думал, что спрошу, существует ли такая вещь, прежде чем я ее напишу. Я знаю, что это похоже на двухстрочный скрипт Perl или Python, но, возможно, есть более стандартный способ сделать это. Если нет, не стесняйтесь размещать решение на вашем любимом языке сценариев, стиль Rosetta Stone .

PS: Может быть, лучшим способом сделать это было бы обобщение repeat, чтобы взять как количество раз для повторения (с -1 значение бесконечности), так и количество секунд, чтобы спать между повторами. Вышеприведенные примеры затем станут:

% repeat 100 0 echo "I will not automate this punishment."
% repeat -1 5 echo "This will get echoed every 5 seconds forever."
399 голосов | спросил dreeves 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:11:13 +0300000000amTue, 17 Feb 2009 03:11:13 +030009 2009, 03:11:13

25 ответов


517

Попробуйте выполнить команду watch.

Usage: watch [-dhntv] [--differences[=cumulative]] [--help] [--interval=<n>] 
             [--no-title] [--version] <command>`

Итак, чтобы:

watch -n1  command

будет запускать команду каждую секунду (ну, технически, каждую секунду плюс время, которое требуется для команды command для запуска в виде watch (по крайней мере, procps и busybox) просто наступает одна секунда между двумя запусками команды command) навсегда.

Вы хотите передать команду exec вместо sh -c, используйте опцию -x:

watch -n1 -x command

В macOS вы можете получить watch из Mac-портов :

port install watch

Или вы можете получить его из Homebrew :

brew install watch
ответил Gregor Brandt 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:22:21 +0300000000amTue, 17 Feb 2009 03:22:21 +030009 2009, 03:22:21
203

Bash

while + sleep:

while true
do 
    echo "Hi"
    sleep 1
done

Вот то же самое, что и сокращенный однострочный (из комментариев ниже):

while sleep 1; do echo "Hi"; done

Использует ; для разделения команд и использует sleep 1 для теста while, так как он всегда возвращает true. Вы можете добавить больше команд в цикл - просто отделите их с помощью ;

ответил 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:13:34 +0300000000amTue, 17 Feb 2009 03:13:34 +030009 2009, 03:13:34
55

Это просто более короткая версия других ответов while+sleep, если вы часто выполняете такие задачи как свою повседневную жизнь, используя это, избавляя вас от ненужных нажатий клавиш, и если ваша команда линия начинает понимать, что это немного легче. Но сначала это начинается со спящего.

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

while sleep 1; do uptime; done
ответил Bekir Dogan 19 Jpm1000000pmSat, 19 Jan 2013 19:53:19 +040013 2013, 19:53:19
40

Одна из проблем, с которой до сих пор звучат все ответы, заключается в том, что время выполнения команды может дрейфовать. Например, если вы выполняете команду sleep 10 между командами, и для выполнения этой команды требуется 2 секунды, она будет запускаться каждые 12 секунд; если требуется много времени для запуска, то в долгосрочной перспективе время его запуска может быть непредсказуемым.

Это может быть именно то, что вы хотите; если это так, используйте одно из других решений или используйте этот, но упростите вызов sleep.

Для одноминутного разрешения задания cron будут выполняться в указанное время независимо от того, сколько времени занимает каждая команда. (Фактически новое задание cron будет запущено, даже если предыдущий все еще работает.)

Вот простой скрипт Perl, который засыпает до следующего интервала, например, с интервалом в 10 секунд команда может выполняться в 12:34:00, 12:34:10, 12:34:20 и т. д. даже если сама команда занимает несколько секунд. Если команда запускает более interval секунд, следующий интервал будет пропущен (в отличие от cron). Интервал вычисляется относительно эпохи, поэтому интервал в 86400 секунд (1 день) будет выполняться в полночь UTC.

 #!/usr/bin/perl

use strict;
use warnings;

if (scalar @ARGV < 2) {
    die "Usage: $0 seconds command [args...]\n";
}

$| = 1;  # Ensure output appears

my($interval, @command) = @ARGV;

# print ">>> interval=$interval command=(@command)\n";

while (1) {
    print "sleep ", $interval - time % $interval, "\n";
    sleep $interval - time % $interval;
    system @command; # TODO: Handle errors (how?)
}
ответил Keith Thompson 12 Jpm1000000pmThu, 12 Jan 2012 15:29:47 +040012 2012, 15:29:47
23

Я думаю, что весь ответ здесь до сих пор слишком запутан, или вместо этого отвечает на другой вопрос:

  • "Как многократно запускать программу, чтобы задержка между X секундами была завершена, а следующая -" .

Реальный вопрос:

  • «Как запустить программу каждые X секунд»

Это две разные вещи, когда команде требуется время для завершения.

Возьмем, к примеру, скрипт foo.sh (притвориться, что это программа, для завершения которой требуется несколько секунд).

#!/bin/bash
# foo.sh
echo `date +"%H:%M:%S"` >> output.txt;
sleep 2.5;
# ---

Вы хотите запускать это каждую секунду, и большинство из них предложит watch -n1 ./foo.sh или while sleep 1; do ./foo.sh; done. Однако это дает результат:

15:21:20
15:21:23
15:21:27
15:21:30
15:21:34

Это не выполняется каждую секунду. Даже с флагом -p, поскольку предлагаемая страница man watch может решить эту проблему, результат будет таким же.

Простой способ выполнить желаемую задачу, к которой нужно прикоснуться, - запустить команду в фоновом режиме. Другими словами:

while sleep 1; do (./foo.sh &) ; done

И это все, что есть.

Вы можете запускать его каждые 500 мс с помощью sleep 0.5 или того, что у вас есть.

ответил swalog 29 Jpm1000000pmWed, 29 Jan 2014 18:42:18 +040014 2014, 18:42:18
17

В bash:

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; done'

(echo может быть заменен любой командой ...

Или в perl:

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"}'

Где print "I will not automate this punishment in absurdum.\n" может быть заменен на «любую» команду, окруженную обратными окнами (`).

И для паузы добавьте оператор sleep внутри цикла for:

bash -c 'while [ 0 ]; do echo "I will not automate this punishment in absurdum."; sleep 1; done'

и

perl -e 'for (;1;) {print "I will not automate this punishment in absurdum.\n"; sleep 1}'
ответил 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:36:15 +0300000000amTue, 17 Feb 2009 03:36:15 +030009 2009, 03:36:15
8

Недавний bash> = 4.2 в соответствии с последним ответом на ядро ​​Linux.

Чтобы ограничить время выполнения, есть без forks ! Используются только встроенные.

Для этого я использую read встроенную функцию вместо sleep. К сожалению, это не будет работать с сеансами notty .

Быстрый function "repeat "по запросу:

repeat () {
   local repeat_times=$1 repeat_delay=$2 repeat_foo repeat_sleep
   read -t .0001 repeat_foo
   if [ $? = 1 ] ;then
       repeat_sleep() { sleep $1 ;}
   else
       repeat_sleep() { read -t $1 repeat_foo; }
   fi
   shift 2
   while ((repeat_times)); do
        ((repeat_times=repeat_times>0?repeat_times-1:repeat_times))
        "${@}"
        ((repeat_times))&& ((10#${repeat_delay//.})) &&
            repeat_sleep $repeat_delay
   done
}

Маленький тест с цитируемыми строками:

repeat 3 0 printf "Now: %(%T)T, Hello %s.\n" -1 Guy
Now: 15:13:43, Hello Guy.
Now: 15:13:43, Hello Guy.
Now: 15:13:43, Hello Guy.

repeat -1 .5 printf "Now: %(%T)T, Hello %s.\n" -1 Guy
Now: 15:14:14, Hello Guy.
Now: 15:14:14, Hello Guy.
Now: 15:14:15, Hello Guy.
Now: 15:14:15, Hello Guy.
Now: 15:14:16, Hello Guy.
Now: 15:14:16, Hello Guy.
Now: 15:14:17, Hello Guy.
Now: 15:14:17, Hello Guy.
Now: 15:14:18, Hello Guy.
Now: 15:14:18, Hello Guy.
^C

В зависимости от детализации и продолжительности поданной команды ...

В последних ядрах Linux есть файл procfile /proc/timer_list, содержащий информацию о времени в наносекундах.

Если вы хотите запускать команду ровно один раз в секунду, ваша команда должна заканчиваться менее чем за секунду! И , вы должны sleep только rest текущей секунды.

Если задержка важнее, и ваша команда не требует значительного времени, вы можете:

command=(echo 'Hello world.')
delay=10
while :;do
    printf -v now "%(%s)T" -1
    read -t $(( delay-(now%delay) )) foo
    ${command[@]}
  done.

Но если ваша цель - получить более тонкую детализацию, вы должны:

Используйте информацию о наносекундах, чтобы подождать до начала второй ...

Для этого я написал небольшую функцию bash:

# bash source file for nano wait-until-next-second

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    ((_c+=${#_timer_list[_i]}))
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_READ=$_c
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
        TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
        break
done
unset _i _timer_list _c
readonly TIMER_LIST_OFFSET TIMER_LIST_READ
waitNextSecondHires() {
    local nsnow nsslp
    read -N$TIMER_LIST_READ nsnow </proc/timer_list
    nsnow=${nsnow%% nsecs*}
    nsnow=$((${nsnow##* }+TIMER_LIST_OFFSET))
    nsslp=$((2000000000-10#${nsnow:${#nsnow}-9}))
    read -t .${nsslp:1} foo
}

После поиска их можно:

command=(echo 'Hello world.')
while :;do
    waitNextSecondHires
    ${command[@]}
  done.

запустите ${command[@]} непосредственно в командной строке, чем сравните с

command=(eval "echo 'Hello world.';sleep .3")
while :;do
    waitNextSecondHires
    ${command[@]}
  done.

это должно дать точно такой же результат.

Нанимает function "repeat "по запросу:

Вы можете указать это:

mapfile  </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
    ((_c+=${#_timer_list[_i]}))
    [[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_READ=$_c
    [[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
        TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
        break
done
unset _i _timer_list _c
readonly TIMER_LIST_OFFSET TIMER_LIST_READ

repeat_hires () {
    local repeat_times=$1 repeat_delay=$2 repeat_foo repeat_sleep repeat_count
    read -t .0001 repeat_foo
    if [ $? = 1 ] ;then
        repeat_sleep() { sleep $1 ;}
    else
        repeat_sleep() { read -t $1 repeat_foo; }
    fi
    shift 2
    printf -v repeat_delay "%.9f" $repeat_delay
    repeat_delay=${repeat_delay//.}
    read -N$TIMER_LIST_READ nsnow </proc/timer_list
    nsnow=${nsnow%% nsec*}
    started=${nsnow##* }
    while ((repeat_times)); do
        ((repeat_times=repeat_times>0?repeat_times-1:repeat_times))
        "${@}"
        ((repeat_times)) && ((10#$repeat_delay)) && {
            read -N$TIMER_LIST_READ nsnow </proc/timer_list
            nsnow=${nsnow%% nsec*}
            nsnow=${nsnow##* }
            (( (nsnow - started) / 10#$repeat_delay - repeat_count++ )) &&
                printf >&2 "WARNING: Command '%s' too long for %f delay.\n" \
                           "${*}" ${repeat_delay:0:${#repeat_delay}-9
                           }.${repeat_delay:${#repeat_delay}-9}
            printf -v sleep "%010d" $((
                10#$repeat_delay - ( ( nsnow - started ) % 10#$repeat_delay ) ))
            repeat_sleep ${sleep:0:${#sleep}-9}.${sleep:${#sleep}-9}
        }
    done
}

Затем попробуйте:

time repeat_hires 21 .05 sh -c 'date +%s.%N;sleep .01'
1480867565.152022457
1480867565.201249108
1480867565.251333284
1480867565.301224905
1480867565.351236725
1480867565.400930482
1480867565.451207075
1480867565.501212329
1480867565.550927738
1480867565.601199721
1480867565.651500618
1480867565.700889792
1480867565.750963074
1480867565.800987954
1480867565.853671458
1480867565.901232296
1480867565.951171898
1480867566.000917199
1480867566.050942638
1480867566.101171249
1480867566.150913407

real    0m1.013s
user    0m0.000s
sys     0m0.016s

time repeat_hires 3 .05 sh -c 'date +%s.%N;sleep .05'
1480867635.380561067
WARNING: Command 'sh -c date +%s.%N;sleep .05' too long for 0.050000 delay.
1480867635.486503367
WARNING: Command 'sh -c date +%s.%N;sleep .05' too long for 0.050000 delay.
1480867635.582332617

real    0m0.257s
user    0m0.000s
sys     0m0.004s
ответил F. Hauri 29 Jpm1000000pmWed, 29 Jan 2014 21:31:54 +040014 2014, 21:31:54
4

У вас есть возможность попробовать это (Bash)?

 forever ()   {
    TIMES=shift;
    SLEEP=shift;
    if [ "$TIMES" = "-1" ]; then  
        while true;
        do 
            [email protected]
            sleep $SLEEP
        done
    else
        repeat "$TIMES" [email protected] 
    fi; }
ответил 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:39:26 +0300000000amTue, 17 Feb 2009 03:39:26 +030009 2009, 03:39:26
4

Perl

 #!/usr/bin/env perl
# First argument is number of seconds to sleep between repeats, remaining
# arguments give the command to repeat forever.

$sleep = shift;
$cmd = join(' ', @ARGV);

while(1) {
  system($cmd);
  sleep($sleep); 
}
ответил dreeves 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:17:07 +0300000000amTue, 17 Feb 2009 03:17:07 +030009 2009, 03:17:07
4

Bash и некоторые из его родственных оболочек имеют удобную нотацию (( ... )), в которой могут быть оценены арифметические выражения.

Итак, как ответ на ваш третий вызов, где и счет повторения, и задержка между каждым повторением должны быть настраиваемыми, вот один из способов сделать это:

repeat=10
delay=1

i=0
while (( i++ < repeat )); do
  echo Repetition $i
  sleep $delay
done

Этот ответ также страдает от временного дрейфа, охватываемого ответом Keith's .

ответил Thor 26 PMpFri, 26 Apr 2013 14:55:22 +040055Friday 2013, 14:55:22
3

Как упоминалось gbrandt, если доступна команда watch, обязательно используйте ее. Однако некоторые Unix-системы не устанавливают его по умолчанию (по крайней мере, они не работают там).

Вот еще одно решение с немного отличающимся синтаксисом и выходом (работает в BASH и SH):

while [ 1 ] ; do
    <cmd>
    sleep <x>
    echo ">>>>>>>>>>>>>" `date` ">>>>>>>>>>>>>>"
done

Изменить: я удалил некоторые "." в последнем выражении эха ... holdover из моих дней Perl;)

ответил 17 FebruaryEurope/MoscowbTue, 17 Feb 2009 03:39:50 +0300000000amTue, 17 Feb 2009 03:39:50 +030009 2009, 03:39:50
3

Если ваше намерение состоит не в том, чтобы отображать сообщение на вашем экране, и если вы могли позволить себе повторить работу с точки зрения минут, crontab , возможно, станет вашим лучшим инструментом. Например, если вы хотите выполнять свою команду каждую минуту, вы должны написать что-то вроде этого в файле crontab:

* * * * * my_precious_command

Пожалуйста, ознакомьтесь с учебником для дальнейшего примера. Кроме того, вы можете легко установить тайминги, используя генератор кода Crontab .

ответил Barun 29 FebruaryEurope/MoscowbWed, 29 Feb 2012 13:54:06 +0400000000pmWed, 29 Feb 2012 13:54:06 +040012 2012, 13:54:06
3

Что, если бы у нас были оба?

Вот идея: только с «интервалом» она повторяется навсегда. С «интервалом» и «раз» он повторяет это количество раз, разделенное «интервалом».

Использование:

$ loop [interval [times]] command

Итак, алгоритм будет:

  • Элемент списка
  • если $ 1 содержит только цифры, это интервал (по умолчанию 2)
  • если $ 2 содержит только цифры, это количество раз (по умолчанию бесконечно)
  • while цикл с этими параметрами
    • спящий интервал
    • Если задано несколько раз, уменьшите значение var до тех пор, пока оно не будет достигнуто

Следовательно:

loop() {
    local i=2 t=1 cond

    [ -z ${1//[0-9]/} ] && i=$1 && shift
    [ -z ${1//[0-9]/} ] && t=$1 && shift && cond=1
    while [ $t -gt 0 ]; do 
        sleep $i
        [ $cond ] && : $[--t]
        [email protected]
    done
}
ответил Baronsed 12 22013vEurope/Moscow11bEurope/MoscowTue, 12 Nov 2013 02:27:28 +0400 2013, 02:27:28
2

Я закончил создание варианта ответа свалога. С его помощью вам пришлось ждать X секунд для первой итерации, я также запускаю мой на переднем плане, поэтому ..

./foo.sh;while sleep 1; do (./foo.sh) ; done
ответил Duane Lortie 13 SatEurope/Moscow2014-12-13T10:44:31+03:00Europe/Moscow12bEurope/MoscowSat, 13 Dec 2014 10:44:31 +0300 2014, 10:44:31
1

Быстрая, грязная и, вероятно, опасная для загрузки, но если вы предприимчивы и знаете, что делаете, поместите ее в repeat.sh и chmod 755 it ,

while true
do 
    eval $1 
    sleep $2 
done

Вызвать его с помощью ./repeat.sh <command> <interval>

В моем здравом смысле говорится, что это, вероятно, злой способ сделать это, верно ли мое здравое чувство?

ответил mallyone 28 FebruaryEurope/MoscowbTue, 28 Feb 2012 22:27:22 +0400000000pmTue, 28 Feb 2012 22:27:22 +040012 2012, 22:27:22
1

Вы можете запустить скрипт из init (добавив строку в /etc /inittab). Этот скрипт должен запускать вашу команду, спя, пока вы хотите подождать, пока не запустите сценарий еще раз, и выйдите из него. Инициалист снова запустит ваш скрипт после выхода.

ответил Roberto Paz 11 12013vEurope/Moscow11bEurope/MoscowMon, 11 Nov 2013 23:01:05 +0400 2013, 23:01:05
1

Легкий способ повторить задание от crontab с интервалом менее одной минуты (пример 20 секунд):

кронтаб: * * * * * script.sh

script.sh:

#!/bin/bash
>>type your commands here.

sleep 20
>>retype your commands here.

sleep 20
>>retype your commands here.
ответил Charles nakhel 29 MaramSat, 29 Mar 2014 01:26:41 +04002014-03-29T01:26:41+04:0001 2014, 01:26:41
1

Вы можете получить мощность от интерпретатора python из оболочки.

python3 -c "import time, os
while True:
    os.system('your command')
    time.sleep(5)

заменить пять в любое время (сек), которое вам нравится.

Внимание: возврат возвращает SHIFT + ВВОД, чтобы возвращать ввод в оболочку. И не забудьте ввести 4 строки SPACE в каждой строке в цикле while.

ответил pah8J 19 J0000006Europe/Moscow 2018, 16:14:34
0

Это решение работает в MacOSX 10.7. Он прекрасно работает.

bash -c 'while [ 0 ]; do \
      echo "I will not automate this punishment in absurdum."; done'

В моем случае

bash -c 'while [ 0 ]; do ls; done'

или

bash -c 'while [ 0 ]; do mv "Desktop/* Documents/Cleanup"; done'

для постоянной очистки рабочего стола.

ответил Dan Ruiz 11 Jpm1000000pmWed, 11 Jan 2012 19:27:08 +040012 2012, 19:27:08
0

Вы можете указать эту рекурсивную функцию:

#!/bin/bash
ininterval () {
    delay=$1
    shift
    $*
    sleep $delay
    ininterval $delay $*
}

или добавьте:

ininterval $*

и вызовите скрипт.

ответил user unknown 5 PMpTue, 05 Apr 2011 16:10:57 +040010Tuesday 2011, 16:10:57
0

Чтобы повторно запустить команду в окне консоли, я обычно запускаю что-то вроде этого:

while true; do (run command here); done

Это работает и для нескольких команд, например, для отображения постоянного обновления часов в окне консоли:

while true; do clear; date; sleep 1; done

ответил Thomas Bratt 24 MonEurope/Moscow2012-12-24T16:09:32+04:00Europe/Moscow12bEurope/MoscowMon, 24 Dec 2012 16:09:32 +0400 2012, 16:09:32
0

... Интересно, сколько сложных решений может быть создано при решении этой проблемы.

Это может быть так просто ...

open /etc/crontab 

поместите туда 1 следующую строку в конец файла, например:

*/NumberOfSeconds * * * * user /path/to/file.sh

Если вы хотите запускать что-то каждые 1 секунду, просто поставьте туда:

*/60 * * * * root /path/to/file.sh 

where that file.sh could be chmod 750 /path/to/file.sh

и внутри этого файла.sh должно быть:

#!/bin/bash 
#What does it do
#What is it runned by

your code or commands

и все!

НАСЛАЖДАЙТЕСЬ!

ответил MIrra 28 FriEurope/Moscow2012-12-28T18:28:54+04:00Europe/Moscow12bEurope/MoscowFri, 28 Dec 2012 18:28:54 +0400 2012, 18:28:54
0
#! /bin/sh

# Run all programs in a directory in parallel
# Usage: run-parallel directory delay
# Copyright 2013 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

if [ $# -eq 0 ]
then
   echo
   echo "run-parallel by Marc Perkel"
   echo
   echo "This program is used to run all programs in a directory in parallel" 
   echo "or to rerun them every X seconds for one minute."
   echo "Think of this program as cron with seconds resolution."
   echo
   echo "Usage: run-parallel [directory] [delay]"
   echo
   echo "Examples:"
   echo "   run-parallel /etc/cron.20sec 20"
   echo "   run-parallel 20"
   echo "   # Runs all executable files in /etc/cron.20sec every 20 seconds or 3 times a minute."
   echo 
   echo "If delay parameter is missing it runs everything once and exits."
   echo "If only delay is passed then the directory /etc/cron.[delay]sec is assumed."
   echo
   echo 'if "cronsec" is passed then it runs all of these delays 2 3 4 5 6 10 12 15 20 30'
   echo "resulting in 30 20 15 12 10 6 5 4 3 2 executions per minute." 
   echo
   exit
fi

# If "cronsec" is passed as a parameter then run all the delays in parallel

if [ $1 = cronsec ]
then
   $0 2 &
   $0 3 &
   $0 4 &
   $0 5 &
   $0 6 &
   $0 10 &
   $0 12 &
   $0 15 &
   $0 20 &
   $0 30 &
   exit
fi

# Set the directory to first prameter and delay to second parameter

dir=$1
delay=$2

# If only parameter is 2,3,4,5,6,10,12,15,20,30 then automatically calculate 
# the standard directory name /etc/cron.[delay]sec

if [[ "$1" =~ ^(2|3|4|5|6|10|12|15|20|30)$ ]]
then
   dir="/etc/cron.$1sec"
   delay=$1
fi

# Exit if directory doesn't exist or has no files

if [ ! "$(ls -A $dir/)" ]
then
   exit
fi

# Sleep if both $delay and $counter are set

if [ ! -z $delay ] && [ ! -z $counter ]
then
   sleep $delay
fi

# Set counter to 0 if not set

if [ -z $counter ]
then
   counter=0
fi

# Run all the programs in the directory in parallel
# Use of timeout ensures that the processes are killed if they run too long

for program in $dir/* ; do
   if [ -x $program ] 
   then
      if [ "0$delay" -gt 1 ] 
      then
         timeout $delay $program &> /dev/null &
      else
         $program &> /dev/null &
      fi
   fi
done

# If delay not set then we're done

if [ -z $delay ]
then
   exit
fi

# Add delay to counter

counter=$(( $counter + $delay ))

# If minute is not up - call self recursively

if [ $counter -lt 60 ]
then
   . $0 $dir $delay &
fi

# Otherwise we're done
ответил user56318 9 Jpm1000000pmThu, 09 Jan 2014 18:32:29 +040014 2014, 18:32:29
0

С помощью zsh и sleep, которая принимает аргументы с плавающей запятой:

typeset -F SECONDS=0 n=0
repeat 100 {cmd; sleep $(((n+=3) - SECONDS))}

Или для forever:

for ((;;)) {cmd; sleep $(((n+=3) - SECONDS))}

Если ваш sleep не поддерживает float, вы всегда можете переопределить его как оболочку вокруг zsh zselect builtin: р>

zmodload zsh/zselect
sleep() zselect -t $((($1 * 100) | 0))
ответил Stéphane Chazelas 26 J0000006Europe/Moscow 2018, 14:34:28
-1
until ! sleep 60; do echo $(date); command; command; command; done

работает для меня.

  1. Мне это не нужно ровно через каждые 60 секунд.
  2. «смотреть» не выполняет команды во всех системах.
  3. «watch» может принимать только одну команду (или файл сценария)
  4. включение сна в условие вместо тела делает цикл более прерываемым (поэтому требование в ответ на аналогичный вопрос о stackoverflow. к сожалению, я могу найти его в данный момент)
  5. Я хочу выполнить его один раз перед задержкой, поэтому я использую до тех пор, пока не будет
ответил Titus 11 J0000006Europe/Moscow 2016, 15:59:01

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132