cron スクリプトはキューとして機能しますか、それとも cron のキューとして機能しますか?

StackOverflow https://stackoverflow.com/questions/226473

  •  03-07-2019
  •  | 
  •  

質問

誰かがすでにこの問題を解決していると確信しています。おそらく私が答えを教えてくれるGoogleの検索用語を間違っているのかもしれませんが、これが私の状況です。

実行したいスクリプトがありますが、スケジュールされた時間にのみ、一度に 1 つだけ実行したいと考えています。(スクリプトを同時に実行することはできません)

ここで厄介な部分は、必要なデータとスケジュールされた時刻を含む「myhappyschedule」というテーブルがあるとします。このテーブルには同時に複数のスケジュール時間を設定でき、それぞれがこのスクリプトを実行します。したがって、基本的に、スクリプトが起動するたびにキューが必要になり、スクリプトが完了するまですべてのキューが待機する必要があります。(スクリプトの実行に 1 分しかかからない場合もありますが、何分もかかる場合もあります)

私がやろうと考えているのは、myhappyschedule を 5 分ごとにチェックし、スケジュールされたものを集めてキューに入れ、別のスクリプトがキュー内の各「ジョブ」またはオカレンスを順番に実行できるようにするスクリプトを作成することです。これはすべて面倒に聞こえます。

長くなりますが、ユーザーが crontab を編集するのではなく、myhappyschedule でスケジュールを設定できるようにしていると言うべきです。

これについて何ができるでしょうか?ファイルロックとスクリプト呼び出しスクリプト?

役に立ちましたか?

解決

exec_statusmyhappytableに追加します(time_startedおよびtime_finishedも可能、擬似コードを参照)

次のcronスクリプトをx分ごとに実行します

cronスクリプトの擬似コード:

[create/check pid lock (optional, but see "A potential pitfall" below)]
get number of rows from myhappytable where (exec_status == executing_now)
if it is > 0, exit
begin loop
  get one row from myhappytable
    where (exec_status == not_yet_run) and (scheduled_time <= now)
    order by scheduled_time asc
  if no such row, exit
  set row exec_status to executing_now (maybe set time_started to now)
  execute whatever command the row contains
  set row exec_status to completed
  (maybe also store the command output/return as well, set time_finished to now)
end loop
[delete pid lock file (complementary to the starting pid lock check)]

この方法では、スクリプトは最初にコマンドが実行されていないかどうかを確認し、指定された瞬間に実行するコマンドがなくなるまで、まだ実行されていないコマンドを最初に実行します。また、データベースにクエリを実行すると、実行されているコマンドを確認できます。

潜在的な落とし穴: cronスクリプトが強制終了された場合、スケジュールされたタスクは<!> quot; executing_now <!> quot;に残ります。状態。それが、最初と最後のpidロックの目的です。cronスクリプトが適切に終了したかどうかを確認します。作成/チェックpidlockの擬似コード:

if exists pidlockfile then
  check if process id given in file exists
  if not exists then
    update myhappytable set exec_status = error_cronscript_died_while_executing_this   
      where exec_status == executing_now
    delete pidlockfile
  else (previous instance still running)
    exit
  endif
endif
create pidlockfile containing cron script process id

他のヒント

スクリプト内でat(1)コマンドを使用して、次回の実行をスケジュールできます。終了する前に、次回の実行時にmyhappyscheduleを確認できます。 cronはまったく必要ありません、本当に。

キューの問題の解決策を調べているときに、この質問に遭遇しました。他の検索者の利益のために、ここに私の解決策があります。

これを、スケジュールどおりにジョブを開始する cron と組み合わせると (同時に実行するようにスケジュールされている場合でも)、あなたが説明した問題も解決します。

問題


  • スクリプトのインスタンスは最大 1 つだけ実行する必要があります。
  • リクエストをキューに入れて、できるだけ早く処理したいと考えています。

つまり。スクリプトへのパイプラインが必要です。

解決:


任意のスクリプトへのパイプラインを作成します。小さな bash スクリプトを使用して実行します (さらに下にあります)。

スクリプトは次のように呼び出すことができます
./pipeline "<any command and arguments go here>"

例:

./pipeline sleep 10 &
./pipeline shabugabu &
./pipeline single_instance_script some arguments &
./pipeline single_instance_script some other_argumnts &
./pipeline "single_instance_script some yet_other_arguments > output.txt" &
..etc

スクリプトは新しいファイルを作成します 名前付きパイプ コマンドごとに。したがって、上記は名前付きパイプを作成します。 sleep, shabugabu, 、 そして single_instance_script

この場合、最初の呼び出しでリーダーが開始され、実行されます。 single_instance_scriptsome arguments 引数として。呼び出しが完了すると、リーダーはパイプから次のリクエストを取得し、次のように実行します。 some other_arguments, 、完了、次を取得など...

このスクリプトは要求プロセスをブロックするため、バックグラウンド ジョブ (最後に &) として呼び出すか、分離されたプロセスとして呼び出します。 at (at now <<< "./pipeline some_script")

#!/bin/bash -Eue

# Using command name as the pipeline name
pipeline=$(basename $(expr "$1" : '\(^[^[:space:]]*\)')).pipe
is_reader=false

function _pipeline_cleanup {
        if $is_reader; then
                rm -f $pipeline
        fi
        rm -f $pipeline.lock

        exit
}
trap _pipeline_cleanup INT TERM EXIT

# Dispatch/initialization section, critical
lockfile $pipeline.lock
        if [[ -p $pipeline ]]
        then
                echo "$*" > $pipeline
                exit
        fi

        is_reader=true
        mkfifo $pipeline
        echo "$*" > $pipeline &
rm -f $pipeline.lock

# Reader section
while read command < $pipeline
do
        echo "$(date) - Executing $command"
        ($command) &> /dev/null
done
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top