先日、Task Spooler というツールを知り*1、少し試してみたところ便利そうだったので、勤め先の社内勉強会で紹介しました。発表資料を公開します。
Task Spooler は、簡易ジョブ管理システムのようなツールです。ジョブをキューに登録しておくと、同時実行数が一定の値*2を超えないように制限しながら、並列に実行してくれます。下記のウェブサイトからダウンロードして利用できます。
Task Spooler - batch is back!
現在の Task Spooler では、ジョブをキューに登録する際に、「指定した先行ジョブが正常終了した場合のみ実行する」という形でジョブの依存関係を記述できますが、指定できる先行ジョブは一つのみという制限があります。これを複数指定できれば、MapReduce のような処理を簡単に実現できるので、この制限は残念なところです。
発表スライドにも書いたように、これには特に本質的な難しさがあるわけではなく、先行ジョブの ID を int 型から int[] 型に変えて管理すれば解決できそうです。公開されているソースコードを実際に変更して、このことを確認してみました。下記のリポジトリのコードでは、-D オプションを複数指定できるようになっています*3。
https://github.com/y-uti/taskspooler
たとえば、次のように実行できます。最初の ts -S 2 で同時実行数を 2 に設定し、その後、ジョブを順番にキューに登録していきます。登録されたジョブのジョブ ID が標準出力に表示されます。3 番目のジョブを登録する際には、ID=0 のジョブと ID=1 のジョブがともに正常終了してから実行することを指示しています。
$ ts -S 2 $ ts sleep 10 0 $ ts sleep 5 1 $ ts sleep -D 0 -D 1 sleep 5 2 $ ts sleep 3 3
このような順序で登録されたジョブは、Task Spooler によって下図のように実行されます*4。開始から 5 秒後に ID=1 のジョブが終了しますが、ID=2 のジョブは ID=0 のジョブが終わるまで実行を開始できません。そのため、ID=3 のジョブが先に実行されます。10 秒後に ID=0 のジョブが終了した後、ID=2 のジョブの実行が開始されます。
*1:「cron + α が欲しい時には ts(Task Spooler) のご利用をご検討下さいというメモ - ようへいの日々精進XP」という記事が話題になっていたことで、このツールを知りました。
*2:この値はユーザが設定できます。
*3:実現可能であることを確認するだけの雑な実装で、指定可能な上限数も 20 個に制限しています。
*4:図は、4 つのジョブの登録がすべて同時に実行されたと仮定した場合です。