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


10

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

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

多分リアルタイムの信号で。うるう秒の適切な処理。幸運を。
mikeserv 2015年

@mikeservでは、気にしないでください。ミリ秒の精度は気にせず、0.5秒と言ってください。
user1032531

あなたは何を成し遂げようとしているのですか?そのような頻度で実行する必要があるタスクは、通常、別の問題の回避策であることがわかりました。
Sobrique 2015年

@Sobriqueその通りです。ポーリングデータロガーの概念実証を行っています。実際には、他の言語でプログラムされますが、これは今のところ機能します。
user1032531 2015年

回答:


16

どうですか:

( # 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:これらすべてのコメント、代替案、および追加の保護のためのサブシェルを使用すると、当初よりもはるかに複雑に見えます。だから、比較のために、ここで私が心配を開始する前に、それはのように見えたものですwaitkill自分で、$!そして隔離の必要性:

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

残りは本当に必要なときだけです。


コードダンプの背後にある理由を説明できますか?
Ismael Miguel

2
また、(mikeservの回答のように)コードがどのシェルで機能するかを引用し、別のシェルの動作が異なるときに混乱しないように:)
ash

@IsmaelMiguel私はコメントが推論を説明するだろうと考えました。何が不明確かわかりません。
Sidhekin、2015年

1
bashマニュアルでは、$!「最後にバックグラウンドに配置されたジョブのプロセスIDに展開されます」とあり、バックグラウンドにsleepは配置されないため、そうではありません。:)
Sidhekin、2015年

1
ワオ。両方の点で間違っています。それはいつ起こったのですか?
mikeserv 2015年

9

あなたには、次のような何かを行うことができbashzshまたはksh

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

これはbashマニュアルが言っていること$SECONDSです:

$SECONDS

  • このパラメーターが参照されるたびに、シェルの呼び出しからの秒数が返されます。に値が割り当てられている場合、$SECONDS以降の参照で返される値は、割り当てからの秒数と割り当てられた値です。場合$SECONDSunset、それがその後にリセットされている場合でも、その特殊な性質を失います。

これが実際の例です:

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

10
20
30
40
50
60
70
80
90
100

2
リセットを回避するにSECONDSは、を実行してくださいsleep "$((10-(($SECONDS-$start_time)%10)))"start_time=$SECONDSループの前に行う必要があります。
ctrl-alt-delor 2015年

@richard-なぜそれを避けるのですか?
mikeserv 2015年

ある日、そのようなループ内から呼び出すスクリプトでそれを使用するためです。そして、あなたはそれがなぜ正しく機能していないのかと思って一日中過ごします。つまり、をリセットしても、ネストされませんSECONDS。最新の編集のようにサブシェルを生成することでも、この問題を回避できます。
ctrl-alt-delor

1
@richard-質問はwhile trueループに関するものだったので、シェルの状態がそれを乗り越えると予想されるとは思いませんでした。とにかく、そのようなループを独自のコンテキストでラップすることは、通常、ベストプラクティスです。そのような状況で、私はより多くのためにそうすることを懸念するだろうtrap「のよりsの日本酒$SECONDSが、酒」。
mikeserv

マイクのおかげで、私は同様のことをしようと考えていました(しかし、具体的な方法はまだわかりませんでした)。しかし、Sidhekinのソリューションは同じことをするように見えますか?私はより良い答えを判断する資格はありませんが、何かを選ぶ義務があると感じました。
user1032531 2015年

3

BASHのみ-コマンドで費やした時間を計算し、10から引くこともできます。

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

バッシュマンから:

TIMEFORMATこのパラメーターの値は、時間予約語が前に付いたパイプラインのタイミング情報を表示する方法を指定するフォーマット文字列として使用されます。%文字は、時間値またはその他の情報に展開されるエスケープシーケンスを導入します。エスケープシーケンスとその意味は次のとおりです。中括弧はオプションの部分を示します。
%%リテラル%。
%[p] [l] R秒単位の経過時間。
%[p] [l] Uユーザーモードで費やされたCPU秒数。
%[p] [l] Sシステムモードで費やされたCPU秒数。
%P CPUの割合。(%U +%S)/%Rで計算されます。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.