X秒ごとにコマンドを実行する

X秒ごとにコマンドを実行する

10秒ごとにコマンドを実行し、バックグラウンドで実行するようにしたい(したがってwatch?を削除します)。すべての回答は次のように表示されますが、実行には11〜14秒かかります。これはどのように達成できますか?

while true; do
    # perform command that takes between 1 and 4 seconds
    sleep 10
done

答え1

どうですか?

( # In a subshell, for isolation, protecting $!
  while true; do
    perform-command & # in the background
    sleep 10 ;
    ### If you want to wait for a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line:
    # wait $! ;
    ### If you prefer to kill a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line instead:
    # kill $! ;
    ### (If you prefer to ignore it, uncomment neither.)
  done
)

ETA:追加の保護のためのこれらの説明、代替案、およびサブシェルを含めると、初めて起動したときよりもはるかに複雑に見えます。比較のために、waitorkillおよびそれらの分離要件について心配する$!前の外観は次のとおりです。

while true; do perform-command & sleep 10 ; done

残りは必要なときにすぐそこにあります。

答え2

bashzsh、またはで次のことができますksh

SECONDS=0
while   command
do      sleep "$((10-(SECONDS%10)))"
done

bashマニュアルにはこう記載されています$SECONDS

$SECONDS

  • このパラメーターが参照されるたびに、シェルが呼び出されてからの秒数が返されます。値がに割り当てられている場合、$SECONDS後続の参照によって返される値は、割り当て後の秒数に割り当てられた値を加算した値です。もし$SECONDSそうならunset、その後リセットされても特別な属性が失われます。

以下は実際の例です。

(   SECONDS=0
    while   sleep   "$((RANDOM%10))"
    do      sleep   "$((10-(SECONDS%10)))"
            echo    "$SECONDS"
    done
)

10
20
30
40
50
60
70
80
90
100

答え3

BASHのみ - コマンドに費やされた時間を計算して10から減算することもできます。

TIMEFORMAT=$'%0R'
while true; do
    T=$({ time command; } 2>&1)
    sleep $(( 10-T ))

BASHの人々から:

TIMEFORMAT このパラメーターの値は、時刻予約語の先頭にあるパイプのタイミング情報の表示方法を指定する書式文字列として使用されます。 % 文字は、時間値やその他の情報に拡張されるエスケープシーケンスを紹介します。エスケープシーケンスとその意味は次のとおりです。中括弧はオプションの部分を表します。
%%リテラル%。
%[p][l]R 経過時間(秒)です。
%[p][l]U ユーザーモードで消費された CPU 時間 (秒)。
%[p][l]S システムモードで消費された CPU 時間 (秒)。
%P CPU パーセントで、 (%U + %S) / %R として計算されます。

オプションのpは、精度、つまり小数点以下の桁数を指定する数値です。値が0の場合、小数点や小数は出力されません。

関連情報