永远每隔X秒重复Unix命令


480

有一个内置的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."

我以为在写之前会问这样的事情是否存在。我知道这就像2行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."

1
为什么不:重复[-t时间] [-n号]命令[args ...]?
乔纳森·莱夫勒

17
凉。不幸的是都在我的Ubuntu和我的AIX 重复命令没有找到。您能做一个type repeat,让我知道消息的来源吗?

3
我也在Ubuntu上,没有重复安装。有关如何安装此程序的任何信息将很有帮助。
罗里

7
repeat是csh和tcsh中的内置命令。
基思·汤普森

2
@ KeithThompson,csh,tcsh 和zsh。虽然它比一个内置一个关键字
斯特凡Chazelas

Answers:


615

尝试watch命令。

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

以便:

watch -n1  command

将永远每秒运行一次命令(从技术上讲,每秒command运行一次,再加上运行时间watch(至少在procpsbusybox实现上仅在两次运行之间睡眠一秒钟command))。

是否要将命令传递给exec而不是sh -c使用-x选项:

watch -n1 -x command

在macOS上,您可以watchMac Ports获得:

port install watch

或者您可以从Homebrew获得它:

brew install watch

2
您可以使用MacPorts进行安装。sudo port install watch

10
也可在自制软件中使用(酿造手表)。
莱尔(Lyle)

28
+1获取新的强大工具。我曾经while true; do X; sleep Y; done-这样更好。
亚当·马坦

4
这个工具的问题(至少在Ubuntu上)是强制全屏显示,因此如果我转储一些定期信息,则会丢失以前的信息。
scorpiodawg 2012年

4
cmdwatch在FreeBSD上被调用(从端口:)sysutils/cmdwatch
Ouki 2014年

243

重击

while+ sleep

while true
do 
    echo "Hi"
    sleep 1
done

这与速记单线一样(从下面的注释中得出):

while sleep 1; do echo "Hi"; done

用于;分隔命令和sleep 1用于while测试,因为它始终返回true。您可以在循环中添加更多命令-只需将它们与;


2
我相信它也可以像在通用Bourne shell中编写的那样工作。
dmckee,2009年

5
@dreeves,使用“;” 作为分隔符,命令可以在一行中执行。以Toony的答案为例
bbaja42 2012年

56
sleep 1始终返回true,因此可以将其用作while条件。不是世界上最易读的东西,而是绝对合法的东西:睡眠1;做回声“嗨”;完成
大卫·科斯塔

3
@David Costa:您的观点很合理,但sleep并不总是返回true。Ī̲使用了这样的循环(尽管延迟更长),这是因为有一种方法可以通过终止睡眠过程来优雅地终止它。
Incnis Mrsi 2015年

2
@IncnisMrsi我没想到,它实际上仅在经过时间后才返回零,而在信号终止时返回非零。谢谢指点出来
大卫·科斯塔

71

这只是其他while+sleep答案的简短版本,如果您经常在日常工作中执行此类任务,那么使用它可以避免不必要的按键操作,并且如果您的命令行开始变得更长一点,则可以使您对此有所了解。但是,这首先要睡觉。

如果您需要跟踪具有单行输出的内容(例如机器负载),这通常很有用:

while sleep 1; do uptime; done

是。这应该记录在UUOC旁边。
2013年

10
而且,如果您希望它像“手表”一样运作,您可以这样做while clear; do date; command;sleep 5; done
Johan

哇,谢谢您的while sleep组合,节省了按键!
乔治Y.

45

到目前为止,所有发布的答案都存在的一个问题是命令的执行时间可能会漂移。例如,如果您sleep 10在两次命令之间执行a ,并且该命令需要2秒钟才能运行,那么它将每12秒钟运行一次。如果要花费可变的时间来运行,那么从长远来看,它的运行时间可能是不可预测的。

这可能正是您想要的。如果是这样,请使用其他解决方案之一,或使用此解决方案简化sleep呼叫。

对于一分钟的解决方案,cron作业将在指定的时间运行,而不管每个命令花费多长时间。(实际上,即使上一个仍在运行,新的cron作业也会启动。)

这是一个简单的Perl脚本,它将一直休眠直到下一个间隔,因此,例如,每隔10秒,该命令可能会在12:34:00、12:34:10、12:34:20等处运行,即使命令本身需要几秒钟。如果命令运行超过interval几秒钟,则将跳过下一个间隔(与cron不同)。该间隔是相对于纪元计算的,因此将在UTC午夜运行86400秒(1天)的间隔。

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


1
在bash简单,以尽量减少漂移(尽管它可能很长的使用窗口漂移,由于睡眠命令和bash本身积累了很小的执行时间): while :; do sleep 1m & command; wait; done
数学

1
@数学:聪明。如果您在当前shell中运行了其他后台进程,它将不起作用(wait将等待所有后台进程)。通过更改waitwait $!$!可以解决此问题,该处是sleep进程的PID 。将其发布为答案,我将对其进行投票。但是它确实会在交互式shell中产生一些无关的输出。
Keith Thompson

29

我认为到目前为止,这里的所有答案要么太复杂,要么回答了另一个问题:

  • “如何反复运行程序,以使程序完成与下一次启动之间有X秒的延迟”

真正的问题是:

  • “如何每X秒运行一个程序”

当命令需要时间才能完成时,这是两件事。

以脚本为例foo.sh(假设这是一个需要花费几秒钟才能完成的程序)。

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

您希望每秒运行一次,大多数都会建议watch -n1 ./foo.shwhile 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

这就是全部。

您可以使用sleep 0.5或每隔500毫秒运行一次。


1
那些对不同答案进行投票的人,不理解您的答案的优雅……
Serge Stroobandt

除非您的程序有副作用,否则这很好。如果程序花费的时间超过间隔,则可能会产生副作用(例如覆盖文件)。如果程序正在等待其他东西,并且其他东西永远消耗,那么您将无限期地启动越来越多的后台作业。请谨慎使用。
John Moeller

4
可以反转后台的顺序,以确保一次运行不超过一个./foo.sh,但每秒运行的速度不超过1: while :; do sleep 1 & ./foo.sh; wait; done
math

是的,它会漂移,每个循环几毫秒,但是会漂移。请date +"%H:%M:%S.%N"在foo.sh怎么看分数会慢慢增加每个循环。
以撒

是的,大多数答案的确没有从字面上解决这个问题。但是几乎可以肯定的是,他们会回答OP的要求。如果OP确实接受了答案,那将是一个更安全的选择。但是,这很好,只要您知道可能的副作用,并且您可以确定命令的平均运行时间不会超过周期时间
Auspex

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"可以用反引号(`)包围的“ any”命令代替。

为了暂停,请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}'

16
while [ 0 ]是一种不好的写法。这意味着它0是一个长度> 0的字符串。 while [ 1 ]或者while [ jeff ]会做同样的事情。最好写while true
Mikel

5
@Mikel:还是while :
Keith Thompson

10

在最近的Linux内核下,基于最近的bash> = 4.2。

为了限制执行时间,没有分叉!仅使用内置的。

为此,我使用read内置函数代替sleep。不幸的是,这不适用于notty会话。

快速函数“ 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内核下,有一个/proc/timer_list包含以纳秒为单位的时间信息的procfile 。

如果您想每秒精确地运行一次命令,那么您的命令必须在不到一秒的时间内结束!从那里,你必须sleep剩余电流第二。

如果延迟更为重要,并且您的命令不需要大量时间,则可以:

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.

这必须给出完全相同的结果。

根据要求雇用函数“ 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

read -t内置的,而sleep不是。这可能会产生边界效应(即,悄悄地敲击[key:return]中断睡眠),但是可以通过测试来解决$foo
F. Hauri 2014年

令人印象深刻的答案
gena2x 2014年

4

想要尝试一下(重击)吗?

forever ()   {
    TIMES=shift;
    SLEEP=shift;
    if [ "$TIMES" = "-1" ]; then  
        while true;
        do 
            $@
            sleep $SLEEP
        done
    else
        repeat "$TIMES" $@ 
    fi; }

我不喜欢shell,因此欢迎进行改进。而且我的发行版中似乎没有“ repeat”命令。

2
repeat特定于csh和tcsh。
基思·汤普森

2
@KeithThompson:和zsh
雷神

4

佩尔

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

4

Bash及其某些同类外壳具有方便的(( ... ))表示法,可以在其中评估算术表达式。

因此,作为您的第三个挑战的答案,即重复次数和每次重复之间的延迟都应是可配置的,这是一种解决方法:

repeat=10
delay=1

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

该答案还因Keith答案中涉及的时间漂移​​而受到影响。


这是最好的。
艾哈迈德·阿威斯

3

如gbrandt所述,如果watch命令可用,则一定要使用它。但是,某些Unix系统默认未安装它(至少它们不在我工作的地方)。

这是另一个语法和输出稍有不同的解决方案(在BASH和SH中有效):

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

编辑:我删除了一些“。” 在最后一个echo语句中...我的Perl日子中的保持状态;)


3
while [ 1 ]仅适用于将1视为字符串,就像一样while [ -n 1 ]while [ 0 ]while [ jeff ]会做同样的事情。 while true更有意义。
Mikel

3

如果您不打算在屏幕上显示消息,并且如果您可以负担分钟的时间来重复工作,那么crontab也许是您最好的工具。例如,如果您希望每分钟执行一次命令,则可以在crontab文件中编写如下代码:

* * * * * my_precious_command

请查看该教程以获取更多示例。另外,您可以使用Crontab Code Generator轻松设置时间。


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]
        $@
    done
}

注意:尽管sleep接受浮点数,但它不适用于浮点数。
13年

2

我最终在swalog的答案上创建了一个变体。有了他,您必须等待X秒才能进行第一次迭代,因此我也在前台运行。

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

1

快速,肮脏和危险的可能启动,但如果你喜欢冒险,知道你在做什么,把这个变成repeat.shchmod 755它,

while true
do 
    eval $1 
    sleep $2 
done

调用 ./repeat.sh <command> <interval>

我的间谍意识说这可能是一种邪恶的方式,我的间谍意识对吗?


8
评估!?做什么的? sleep $1; shift; "$@"或类似的会更好。
Mikel

邓诺为什么这是-2。评估可能是过大的……除非您需要。使用Eval,您可以将诸如重定向之类的内容输入命令行。
2013年

1

您可以从init运行脚本(在/ etc / inittab中添加一行)。该脚本必须运行您的命令,等待您想要等待的时间,直到再次运行该脚本,然后退出。退出后,Init将再次启动脚本。


1

从crontab以少于一分钟的时间间隔重复作业的简单方法(例如20秒):

crontab:* * * * * script.sh

script.sh:

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

sleep 20
>>retype your commands here.

sleep 20
>>retype your commands here.

1

您可以从shell的python解释器获取功能。

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

在您喜欢的任何时间(秒)替换五个。

注意:返回使用SHIFT + ENTER在shell中返回输入。并且不要忘记在while循环的每一行中键入4 SPACE缩进。


请注意,pythonos.system()执行Shell来解释命令行,因此调用python在循环中运行Shell以定期运行命令有点过头。您不妨在Shell中做所有事情。
斯特凡Chazelas

我同意你的看法。但是,如每个循环中所述,睡眠时间为5秒。因此,启动新外壳所产生的额外费用可以忽略。如果此成本使周期长于预期,则可以根据需要减少一些睡眠时间。
pah8J

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'

不断清理我的桌面。


1
您的意思是在那里有sleep命令吗?
基思·汤普森

4
while [ 0 ]是写无限循环的奇怪方法;它之所以有效,是因为该test命令(也称为[)将非空字符串视为true。 while : ; do ... ; done更为惯用,或者如果您愿意,可以使用while true ; do ... ; done
基思·汤普森

0

您可以获取此递归函数:

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

或添加:

ininterval $*

并调用脚本。


0

要在控制台窗口中反复运行命令,我通常会运行以下命令:

while true; do (run command here); done

这也适用于多个命令,例如,在控制台窗口中显示不断更新的时钟:

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


为什么要下票?通过将示例复制并粘贴到终端窗口中,可以看到这是一个可行的解决方案。
Thomas Bratt 2013年

我认为您被否决了,因为这有点危险并且会占用CPU。
ojblass

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

0

使用zshsleep接受浮点参数的实现:

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

forever

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

如果你sleep不支持浮点数,你总是可以重新定义它作为包装器zshzselect内置:

zmodload zsh/zselect
sleep() zselect -t $((($1 * 100) | 0))

-1

...我想知道解决这个问题时能创造多少复杂的解决方案。

可能很容易...

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

在该file.sh内部应为:

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

your code or commands

就这样!

请享用!


6
这是不正确的。* / 60每60分钟运行一次,* / 5例如每5分钟运行一次。
mika

1
秒在crontab上不允许使用
GAD3R

在回答错误之前先测试一下自己的东西。
sjas

-1
until ! sleep 60; do echo $(date); command; command; command; done

为我工作。

  1. 我不需要每60秒一次
  2. “监视”并不监视所有系统上的命令
  3. “监视”只能接受一个命令(或脚本文件)
  4. 将睡眠置于身体而不是身体的状态可以使循环更好地被中断(因此在对stackoverflow的类似问题的答复中提出了要求。不幸的是,我现在可以找到它)
  5. 我想在延迟之前执行一次,所以我使用直到代替

我只是注意到,“直到”显然也要在第一次迭代之前执行睡眠。有什么办法可以将条件放在bash循环的末尾?
泰特斯(Titus)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.