このスクリプトは、2つのインスタンスを同時に実行するのではなく、15秒ごとにプログラムを実行しますか?

このスクリプトは、2つのインスタンスを同時に実行するのではなく、15秒ごとにプログラムを実行しますか?

存在するhttps://unix.stackexchange.com/a/11105/674、Gilesは次のように書きました。

次のcrontab行はsome_job15秒ごとに始まります。

* * * * * 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」の次のインスタンスが送信されないようにします。

break1分以内に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秒間隔を決定します。次に、操作を再開する前に、その時間に達するまで待ちます。

おすすめ記事