
存在するhttps://unix.stackexchange.com/a/11105/674、Gilesは次のように書きました。
次のcrontab行は
some_job
15秒ごとに始まります。* * * * * for i in 0 1 2; do some_job & sleep 15; done; some_job
スクリプトは、操作が15秒以上かかることを前提としています。次の少し複雑なスクリプトでは、時間がかかりすぎる場合は、次のインスタンスを実行できなくなります。
date
サポートされている%s
形式(GNUやBusyboxなど)に依存するため、Linuxでは問題はありません。 crontabに直接入力する場合は、%
crontab行に表示されるように文字を作成する必要があります。\%
end=$(($(date +%s) + 45)) while true; do some_job & [ $(date +%s) -ge $end ] && break sleep 15 wait done [ $(date +%s) -ge $(($end + 15)) ] || some_job
しかし、15秒ごとにタスクを実行する必要がある場合は、cronがおそらく間違ったアプローチである可能性があることを指摘したいと思います。 uniceは寿命の短いプロセスに適していますが、15秒ごとにプログラムを起動するオーバーヘッドは無視できません(プログラムの要件によって異なります)。アプリケーションを実行し続け、15秒ごとにタスクを実行することはできませんか?
これが正しいか
このスクリプトはcronとして実行しないでください。
このスクリプトは、今後15秒ごとに実行されている「some_job」インスタンスを送信しようとし、「some_job」を実行しているインスタンスがすでに存在する場合は、「some_job」の次のインスタンスが送信されないようにします。
break
1分以内に45〜59秒の間に「some_job」インスタンスが最初に送信されると、スクリプトが実行されます。その後、スクリプトはwhileループから抜け出し、スキップしてsleep
インスタンスwait
の実行が完了するようにします。ループ外の次のコマンドでは、条件はfalseになり(時間はまだ1分あたり45〜59秒であるため)、スクリプトは "some_job"の最後のインスタンスを送信します。これで、「some_job」インスタンスが2つ実行されていますが、これは望ましくありません。正しいですか?
このようにスクリプトを書くとどうでしょうか?
end=$(($(date +%s) + 60))
while true; do
some_job &
sleep 15
wait
[ $(date +%s) -ge $end ] && break
done
ありがとうございます。
答え1
some_job
設定を有効にすると、( date; sleep 5; echo OK )
15秒ごとに合計4つのインスタンスが作成されます。 5秒遅延(つまり)ではなく20秒遅延を使用すると、( date; sleep 20; echo OK )
20秒間隔で3つのインスタンスを起動できます。
あなたのコードが機能しないので、そのように書くことはできません。
ところで、Gilesのコードは私には機能しません。 (5つのインスタンスがあり、最後のインスタンスは4番目のインスタンスが完了する前に開始されます。)
これが私が思うコードです。 5秒の作業で4回の実行を得ました。 20秒の作業で2回の実行を得ました。
#!/bin/bash
#
echo START $(date)
some_job() { echo JOB BEGIN $(date); sleep 20; echo JOB END $(date); }
begin=$(date +%s)
interval=15
duration=60
while :
do
some_job
now=$(date +%s)
[[ $now -ge $((begin + duration)) ]] && break
rem=$(( (now - begin) % interval))
[[ $rem -eq 0 ]] && rem=interval
delay=$((interval - rem))
[[ $((now + delay)) -ge $((begin + duration)) ]] && break
sleep $delay
done
echo FINISH $(date)
操作が完了した後、このコードはモジュロ演算子を使用して%
次の15秒間隔を決定します。次に、操作を再開する前に、その時間に達するまで待ちます。