Bashジョブキュー

こんにちは、habrazhiteliとhabrachitateli!

最近、次のタスクを行いました。ファイルの特定のディレクトリを監視する必要があり、その中にファイルが表示された場合、このファイルをより安全な他の場所に転送し、長時間実行する必要があります。 すべてが単純なように見えますが、状況は、同時に複数のファイルを処理することが不可能であるという事実に隠れています(処理は、1つのIPから多くのダウンロードを許可しないブルジョアサーバーからファイルをプルします)。

ジョブキュー(FIFO)がすぐに思い浮かびましたが、bashでやりたいと思います(これはまだまだ先です)。 既製のソリューションが必要な人のために-habrakatをお願いします。



この記事は、bashに関してFIFOの文字を最初に聞く初心者を対象としています。





何をするかについて簡単に説明します。1つずつ実行する必要があるチームのキューを作成します。 キューを監視するスクリプトは、jobq.lock ロッカーファイルをチェックします 。 存在しない場合、誰もタスクを実行せず、次のタスクを安全に実行できます。 もしそうなら、あなたはその行から何も読む必要はなく、達成感を持って安全に去ることができます。



まず、スクリプトのキューと場所を作成します。

umask 077 mkdir -p ~/jobs/var mkfifo ~/jobs/var/jobq mkdir -p ~/jobs/bin
      
      





binには起動されるスクリプトがあり、 varにはキューに関連するすべてのもの(実際にはjobqキュー自体 、およびjobq.lock file- locker )があります。

作業フォルダー、入力フォルダー、および出力フォルダーも必要です。 私の場合、これは〜/ jobs / Input〜/ jobs / Workおよび〜/ jobs / Outputです



次に、スクリプトの記述を開始します。 それらの3つがありました。

  1. 新しいデータを追跡して転送する
  2. 新しいデータをキューに送信します(このスクリプトは個別に送信されます-理由についてはコメントで確認できます)
  3. 実際には、キューをチェックし、そこからジョブを実行します




番号順に始めましょう( $ HOME / jobs / bin / mover.sh

 #!/bin/bash # ,         #       FILES_LIST=( $(ls $HOME/jobs/Input) ) #       for raw_file in ${FILES_LIST[@]}; do mv $HOME/jobs/Input/$raw_file $HOME/jobs/Work/ #   ,  .  ,     ,      filename=$(basename $raw_file) #      name=${filename%.*} #         mkdir -p $HOME/jobs/Output/$name #    #2,      . #           #     $HOME/complicated_task.sh -i $HOME/jobs/$raw_file -o $HOME/jobs/Output/$name >> $HOME/jobs/Output/$name/task.log $HOME/jobs/submit.sh "$HOME/complicated_task.sh -i $HOME/jobs/$raw_file -o $HOME/jobs/Output/$name >> $HOME/jobs/Output/$name/task.log" done
      
      





このスクリプトでは、すべてが非常に簡単です。 そしてまあ(願っています!)コメントでアクションを説明しました。

crontab割り当てを作成するための残りはほとんどありません。 このスクリプトを毎分実行します

 crontab -e * * * * * $HOME/jobs/bin/mover.sh
      
      







ジョブをキューに入れる2番目のスクリプト( $ HOME / jobs / bin / submit.sh )に渡します。

 #!/bin/bash # submit.sh. #      #     ,     , #   ,       . #        # (    &  ) echo $* > $HOME/jobs/var/jobq &
      
      







実際、タスクの最後にを付けないと、スクリプトはハングし、前のすべてのタスクの終了を待ちます。 なぜこれを我慢するのですか? バックグラウンドに送信します。



そして最後に、この機会の主人公、キューを読み取り、そこからタスクを実行するスクリプト( $ HOME / jobs / bin / execute.sh ):

 #!/bin/sh # execute.sh #         # jobq.lock - , ,      #    ,     test -f $HOME/jobs/var/jobq.lock && exit 0 #    ,     touch $HOME/jobs/var/jobq.lock || exit 2 #   read job < $HOME/jobs/var/jobq #       : date >> $HOME/jobs/jobs.log echo " RUN: $job" >> $HOME/jobs/jobs.log echo "" >> $HOME/jobs/jobs.log eval $job #   status=$? #  ,   rm -f $HOME/jobs/var/jobq.lock || exit 3 #     ,      exit $status
      
      







そして再び、友人crontab 'yの新しいタスクを作成します。

 crontab -e * * * * * $HOME/jobs/bin/execute.sh
      
      







このようなシステムは数週間着実に機能しており、私はここに書くことにしました-突然誰かがそれを必要とするでしょう。



All Articles