x秒ごとにUnixコマンドを永久に繰り返す


481

repeat最初の引数がコマンドを繰り返す回数である組み込みのUnixコマンドがあります。コマンドは(引数付き)の残りの引数で指定されます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 time] [-n number]コマンド[args ...]を繰り返しますか?
ジョナサンレフラー

17
クール。残念ながら、私のUbuntuとAIXの両方のリピートコマンドが見つかりません。をしてtype repeat、どこから来たのか教えてもらえますか?

3
私もUbuntuを使用していますが、繰り返しインストールする必要はありません。これをインストールする方法に関する情報は役立ちます。
ロリー

7
repeatcshおよびtcshの組み込みコマンドです。
キーストンプソン

2
@KeithThompson、CSH、tcshのとzshの。それは組み込みよりもキーワードだけれども
ステファンChazelas

回答:


616

watchコマンドを試してください。

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

そのため:

watch -n1  command

コマンドを毎秒実行します(厳密には、1秒ごとに、少なくとも(および実装)が2回の実行の間に1秒だけスリープcommandするためにかかる時間)、永久に実行します。watchprocpsbusyboxcommand

exec代わりにコマンドを渡しますか?オプションをsh -c使用し-xます:

watch -n1 -x command

macOSでは、Mac Portswatchから取得できます。

port install watch

または、Homebrewから入手できます。

brew install watch

2
MacPortsを使用してインストールできます。sudoポートインストールウォッチ

10
homebrew(brew install watch)でも利用できます。
ライル

28
+1新しい強力なツール。私は以前while true; do X; sleep Y; done-これはずっと良いです。
アダムMatan

4
このツールの問題(少なくともUbuntuで)は、フルスクリーンを強制するため、定期的な情報をダンプすると、以前の情報が失われます。
さそり座

4
cmdwatchFreeBSD で呼び出されます(ポートから:)sysutils/cmdwatch
Ouki 14年

243

バッシュ

while+ sleep

while true
do 
    echo "Hi"
    sleep 1
done

これは、簡単なワンライナーと同じものです(下のコメントから):

while sleep 1; do echo "Hi"; done

使用する;コマンドを分離し、使用するsleep 1ためにwhile、それは常にtrueを返しますので、テスト。より多くのコマンドをループに入れることができます。;


2
同様に、一般的なBourneシェルで記述されたとおりに機能すると思います。
dmckee 2009

5
@dreeves、「;」を使用 区切り文字として、コマンドは1行で実行できます。一例としてトゥーニーの答えを見てください
bbaja42

56
sleep 1は常にtrueを返すため、while条件として使用できます。世界で最も読みやすいものではありませんが、絶対に合法です:while sleep 1; 「こんにちは」とエコーします。完了
デビッドコスタ

3
@David Costa:あなたは妥当なポイントを挙げましたsleepが、常に真を返すとは限りません。suchこのようなループを使用しました(より長い遅延はありますが)。つまり、スリーププロセスを強制終了してループを正常に終了する方法があるためです。
Incnis MRSI

2
@IncnisMrsi私はそれを考えていませんでしたが、実際には時間が経過したときにのみゼロを返し、シグナルによって終了したときにゼロ以外を返します。それを指摘していただきありがとうございます
デビッドコスタ

71

これは他のwhile+sleep回答の短いバージョンです。この種のタスクを毎日のルーチンとして頻繁に実行している場合、これを使用すると不必要なキーを押す必要がなくなり、コマンドラインがこれを理解し始めると少し簡単になります。しかし、これは最初に寝ることから始まります。

これは、マシンの負荷のような1行の出力があるものに従う必要がある場合に一般的に役立ちます。

while sleep 1; do uptime; done

はい。これはUUOCの隣に文書化する必要があります。
ヨハン

10
また、「時計」のように動作させたい場合は、できることです。while clear; do date; command;sleep 5; done
ヨハン

while sleepわあ、組み合わせてくれてありがとう、キーストロークを節約できます!
ジョージY.

45

これまでに投稿されたすべての回答にある問題の1つは、コマンドの実行時間がドリフトする可能性があることです。たとえば、sleep 10コマンド間でコマンドを実行し、コマンドの実行に2秒かかる場合、12秒ごとに実行されます。実行に時間がかかる場合、長期的には実行時間が予測不能になる可能性があります。

これはまさにあなたが望むものかもしれません。その場合、他の解決策のいずれかを使用するか、この解決策を使用してsleep呼び出しを簡素化します。

1分間の解決では、各コマンドにかかる時間に関係なく、cronジョブは指定された時間に実行されます。(実際には、前の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?)
}

参照してください。この他の質問
ステファンChazelas

1
ドリフトを最小限に抑えるためのbashの単純化(sleepコマンドとbash自体の小さな実行時間の蓄積により、非常に長い使用期間にわたってドリフトする可能性があります): while :; do sleep 1m & command; wait; done
math

1
@数学:賢い。現在のシェルで他のバックグラウンドプロセスを実行している場合は動作しません(waitすべてのプロセスを待機します)。これは、プロセスのPIDをに変更するwaitことwait $!で修正できます。これを回答として投稿してください。投票します。ただし、インタラクティブシェルでは無関係な出力が生成されます。$!sleep
キーストンプソン

29

ここまでのすべての答えは複雑すぎるか、代わりに別の質問に答えていると思います。

  • 「プログラムが終了してから次の開始までにX秒の遅延が生じるようにプログラムを繰り返し実行する方法」

本当の質問は:

  • 「X秒ごとにプログラムを実行する方法」

これらは、コマンドの完了に時間がかかる場合の2つの非常に異なるものです。

たとえば、スクリプトを使用します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、何を使用することもできます。


1
別の答えに投票する人は、...あなたの答えの優雅さを理解していない
セルジュStroobandt

プログラムに副作用がない限り、これは良いことです。プログラムが間隔よりも長くかかる場合、副作用が干渉する可能性があります(ファイルの上書きなど)。プログラムが他の何かを待っており、他の何かが永遠に取っている場合、あなたは無期限にますます多くのバックグラウンドジョブを開始しています。注意して使用してください。
ジョンモーラー

4
1以下./foo.shが一度に実行されることを保証するために、バックグラウンド化の順序を逆に、しかし、可能性が全く速い毎秒1よりません: while :; do sleep 1 & ./foo.sh; wait; done
数学

はい、各ループで数ミリ秒ドリフトしますが、ドリフトします。作る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"backticks( `)で囲まれた" 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
ミケル

5
@Mikel:またはwhile :
キーストンプソン

10

最近のLinuxカーネルでの4.2以上の最近のbashベースの回答。

実行時間を制限するために、フォークはありません!組み込みのみが使用されます。

このため、の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があります。

コマンドを1秒ごとに1回だけ実行する場合、コマンドは1秒未満で終了する必要があります!そしてそこから、あなたは現在sleep残りの秒だけをする必要があります。

遅延がより重要であり、コマンドにかなりの時間を必要としない場合、次のことができます。

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

しかし、目標がより細かい粒度を取得することである場合、以下を行う必要があります。

ナノ秒情報を使用して、1秒の開始まで待機します...

このために、少し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ではありません。([:リターンキー]静かに中断すなわち打つこれは、境界効果が持っている可能性が睡眠を)が、これは、テストすることによって治療することができ$foo
F. HAURI

非常に印象的な答え
gena2x 14年

4

これを試してみてください(Bash)?

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

私はシェルに熱中しないので、改善を歓迎します。そして、私のディストリビューションには「繰り返し」コマンドはないようです。

2
repeatcshおよびtcshに固有です。
キーストンプソン

2
@KeithThompson:and zsh-
トール

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

4

Bashとその親族のシェルには、(( ... ))算術式を評価できる便利な表記法があります。

したがって、繰り返し回数と各繰り返し間の遅延の両方を構成できるようにする必要がある3番目の課題に対する答えとして、次の1つの方法があります。

repeat=10
delay=1

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

この回答には、キースの回答で説明されているタイミングのずれもあります


これが最高でした。
アフマドアワイス

3

gbrandtで述べたように、watchコマンドが使用可能な場合は、必ず使用してください。ただし、一部のUnixシステムでは、デフォルトでインストールされていません(少なくとも私が働いている場所にはインストールされていません)。

構文と出力がわずかに異なる別のソリューションを次に示します(BASHとSHで機能します)。

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

編集:「。」を削除しました 最後のエコー文で...私のPerl時代からのホールドオーバー;)


3
while [ 1 ]1がのように文字列として扱われるため、機能しますwhile [ -n 1 ]while [ 0 ]またはwhile [ jeff ]同じことをします。 while trueはるかに理にかなっています。
ミケル

3

画面にメッセージを表示するのではなく、分単位でジョブを繰り返す余裕がある場合は、おそらくcrontabが最適なツールです。たとえば、コマンドを毎分実行する場合は、crontabファイルに次のように記述します。

* * * * * my_precious_command

さらなる例については、チュートリアルをご覧ください。また、Crontab Code Generatorを使用してタイミングを簡単に設定できます。


3

両方持っていたら?

ここにアイデアがあります:「間隔」だけで、それは永遠に繰り返されます。「interval」と「times」では、「interval」で区切られたこの回数だけ繰り返されます。

使用法:

$ loop [interval [times]] command

したがって、アルゴリズムは次のようになります。

  • リストアイテム
  • $ 1に数字のみが含まれる場合、それは間隔です(デフォルトは2)
  • $ 2が数字のみを含む場合、それは回数(デフォルトは無限)です
  • これらのパラメーターを使用したwhileループ
    • スリープ「インターバル」
    • 何度も指定されている場合は、それに達するまで変数をデクリメントします

したがって:

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受け入れられますが、フロートでは機能しません。
男爵

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; "$@"または同様の方がはるかに良いでしょう。
ミケル

なぜこれが-2なのか。evalは過剰な場合があります...必要な場合を除きます。Evalを使用すると、コマンドラインにリダイレクトなどの情報を取得できます。
ヨハン

1

initからスクリプトを実行できます(/ etc / inittabに行を追加)。このスクリプトはコマンドを実行し、スクリプトを再度実行するまで待機する時間だけスリープし、終了する必要があります。Initは終了後にスクリプトを再び開始します。


1

crontabから1分未満の間隔(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

シェルからpythonインタープリターからパワーを取得できます。

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

あなたが好きな時間(秒)で5を置き換えます。

重要:シェルで入力を返すには、Shiftキーを押しながらEnterキーを押します。また、whileループの各行に4 スペースのインデントを入力することを忘れないでください。


ことに注意してくださいpythonさんがos.system()そう呼び出し、コマンドラインを解釈するためにシェルを実行しpython、定期的にコマンドを実行するループ内でシェルを実行するようにすると、ビット過剰です。シェルですべてを行うこともできます。
ステファンシャゼラス

仰るとおりです。ただし、各ループで説明したように、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


なぜ下票なのですか?例をコピーしてターミナルウィンドウに貼り付けると、これが実用的なソリューションであることがわかります。
トーマスブラット

少し危険であり、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

zshし、sleep浮動小数点の引数を受け付け実装:

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分ごとに実行されます。
ミカ

1
秒はcrontabでは許可されていません
-GAD3R

間違ったたわごとで答える前にあなたのものをテストしてください。
19:31にsjas

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

私のために働く。

  1. 60秒ごとに正確に必要というわけではありません
  2. 「監視」はすべてのシステムでコマンドを監視するわけではありません
  3. 「ウォッチ」は、1つのコマンド(またはスクリプトファイル)のみを取ることができます
  4. ボディの代わりに状態をスリープ状態にすると、ループがより中断可能になります(したがって、stackoverflowでの同様の質問への応答のクレーム。残念ながら、現時点でそれを見つけることができます)
  5. 遅延の前に一度実行したいので、whileではなくuntilを使用します

最初の反復の前に、「まで」明らかにスリープが実行されることに気付きました。bashのループの終わりに条件を置く方法はありますか?
タイタス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.