「4:00」などの特定の時刻が次に発生するまでスリープする一連のコマンドまたは単一のコマンドが必要です。
どうすればいいでしょうか?
現在実行中のスクリプトを離れてはならないため、コマンドat
または cronjob はオプションではありません。
私が話している具体的なケースは、画面で実行されているスクリプトです。スクリプトのどこかの時点で必要となる重要な変数が多数格納されているため、スクリプト自体によってスクリプトの実行を停止しないことが非常に重要です。スクリプトは必ずしも定期的に実行されるわけではありません。特定の時間に実行する必要があるだけです。
スクリプトがファイルや、cronjobs や他の画面などの他のタスクを作成する必要がある場合、非常に便利です。これは単に設計の問題です。
素晴らしいアイデアが浮かんだ。
difference=$(($(date -d "4:00" +%s) - $(date +%s)))
if [ $difference -lt 0 ]
then
sleep $((86400 + difference))
else
sleep $difference
fi
もっと良いアイデアはありますか?
ご要望があればさらに情報を追加します!
答え1
terdon の提案は有効ですが、私の提案の方が効率的だと思います。
difference=$(($(date -d "4:00" +%s) - $(date +%s)))
if [ $difference -lt 0 ]
then
sleep $((86400 + difference))
else
sleep $difference
fi
これは、指定された時間と現在の時間の差を秒単位で計算します。数値が負の場合、スリープする必要がある秒数を取得するために 1 日の秒数 (正確には 86400) を加算する必要があります。数値が正の場合、それをそのまま使用できます。
答え2
シェル スクリプトであると仮定すると、次のように動作するはずです。
while [ $(date +%H:%M) != "04:00" ]; do sleep 1; done
これは 24 時間制です。これを午前 4 時と午後 4 時の両方で継続したい場合は、代わりに以下を使用します。
while [ $(date +%I:%M) != "04:00" ]; do sleep 1; done
答え3
の上オープンBSD*/5
5分間の短縮には次の方法があります。crontab(5)
ジョブを00
時間単位のジョブに分割します (同じタスクを正確な間隔で実行しながら、生成される電子メールの数を減らすため)。
#!/bin/sh -x
for k in $(jot 12 00 55)
do
echo $(date) doing stuff
sleep $(expr $(date -j +%s $(printf %02d $(expr $k + 5))) - $(date -j +%s))
done
注意:date(1)
また、sleep(1)
最終反復では、60
分は有効な時間ではないため (有効な場合を除く)、設計上、電子メール レポートを受け取る前に余分な時間を待つ必要はありません。
また、反復処理の 1 つに割り当てられた 5 分以上かかる場合、sleep
同様に設計上、まったくスリープせずに失敗します (負の数値がコマンド ライン オプションとして解釈されるため、次の時間や永遠に折り返されることはありません)。これにより、割り当てられた 1 時間以内にジョブが完了することが保証されます (たとえば、反復処理の 1 つだけが 5 分を少し超える場合、次の時間に折り返されることなく、追いつく時間がまだあります)。
のprintf(1)
date
分の指定には正確に 2 桁の数字が必要なため、これが必要です。