バッチについて
Google Cloud Batchについて前回の記事の続きになります。基本的な事項はこちらから。
つくったもの
mp4をエンコーディングする公式チュートリアルに手を加えて、より手軽にバッチ処理を開始するスクリプトを作成しました。コードは以下のレポジトリにあります。
基本的な仕組みとしては、starter.sh
を実行すると、job.json.template
、task.sh.template
から必要なファイルが生成され、バッチにjobが登録されます。
ディレクトリ構成は以下の通り。
compressing/
├── starter.sh
├── job.json.template
├── task.sh.template
└── input/
├── photobook-a.pdf
├── photobook-b.pdf
└── photobook-c.pdf
input
以下にphotobookのPDFが格納されており、これをバッチ処理してファイルサイズの小さなPDFを生成します。実際には、バケット内に配置されたPDFのファイル名とファイルの数に規則性はなくバラバラの状況を想定しています。
使用方法
まずはバッチのAPIを有効にします。
gcloud services enable batch.googleapis.com
Cloud Storageにバケットを作成してinput
ディレクトリをコピーします。
gsutil mb -p [PROJECT_ID] -b on -l US gs://[BUCKET_NAME]
gsutil cp -R input gs://[BUCKET_NAME]
starter.shを編集して、[BUCKET_NAME]
を作成したバケット名に変更します。
バッチによる処理の対象は、拡張子.pdfのファイル全てとしています。
BUCKET_NAME="[BUCKET_NAME]"
gcsFilePaths=$(gsutil ls gs://$BUCKET_NAME/input | grep .pdf) #All pdf files in bucket will be proccessed.
準備ができたらstarter.sh
を実行します。
Note: テンプレートからファイルを生成するためenvsubst
コマンドを使用しています。インストールされているかはwhich envsubst
で確認。コマンドのパスが返ってこない場合、gettext
パッケージを先に入れてください。
bash starter.sh
テンプレートから必要なファイルが生成され、バッチにjobが登録されます。少しすると、PDFの圧縮が始まります。
クラウドコンソールを開くと、以下のように進行中のjobが確認できます。
starter.shがやっていること
- バケット内のPDFファイルのファイル名を取得する
- 各PDFファイルを圧縮する
task.sh
を生成する - ファイルの総数=タスク数として
job.json
を生成する - 新規のバッチjobを作成する
task.shの生成
バッチが実行するタスクは、job.json
に記述します。
"script": {
"text": "bash /mnt/share/input/task${BATCH_TASK_INDEX}.sh"
}
"taskCount": 3,
タスクが実行されるたびに${BATCH_TASK_INDEX}
がカウントアップしていきます。例えば、上記の例であれば、task0.sh task1.sh task2.shとtaskCount
の数だけshファイルが実行されます。
さてstarter.sh
はというと、バケット内の各PDFファイルに対応するtask.sh
を生成します。
### Create task.sh files
echo "Creating each task.sh files"
TASK_COUNT=0
for gcsFilePath in $gcsFilePaths
do
FILE_NAME=${gcsFilePath##*/};
export FILE_NAME
cat task.sh.template | envsubst '$FILE_NAME' > $temp_dir/task$TASK_COUNT.sh
TASK_COUNT=`expr $TASK_COUNT + 1`
done
gsutil -m cp $temp_dir/task*.sh gs://$BUCKET_NAME/input/
starter.sh
実行後のgs://[BUCKET_NAME]/input
は以下のようになります。
input
├── photobook-a.pdf
├── task0.sh
├── photobook-b.pdf
├── task1.sh
......
生成されたtask0.sh
の中身を見てみましょう。
gsutil cat gs://[BUCKET_NAME]/input/task0.sh
#!/bin/bash
sudo apt-get -y update
sudo apt-get -y install ghostscript
filename=photobook-a.pdf # ここに圧縮したいPDFのファイル名が入る
dir=/mnt/share
infile=$dir/input/$filename
outfile=$dir/output/${filename/.pdf/_compressed.pdf}
vopts="-sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH -dQUIET"
mkdir -p $dir/output
gs $vopts -sOutputFile=$outfile $infile
ポイントとしては、starter.sh
がバケットから取得したPDFファイル名$FILE_NAME
を、task.sh.template
に渡しているので、生成されたtask0.sh
自体はPDFのファイル名がハードコーディングされたスクリプトになっています。バッチがtask${BATCH_TASK_INDEX}.sh
を順々に実行していくことで、それぞれのPDFファイルの圧縮処理が行われる、という訳です。
タスクの内容を変更したい場合は、task.sh.template
を変更してください。
job.jsonの生成
あとは、task.sh
の数だけバッチにタスクを実行して欲しいので、TASK_COUNT
の値をjob.json.template
に渡して、job.json
を生成します。
### Create job.json
echo "Creating job.json"
export BUCKET_NAME
export TASK_COUNT
cat job.json.template | envsubst '$BUCKET_NAME $TASK_COUNT'> $temp_dir/job.json
並列するタスク数や、マシーンタイプといったパラメーターは、job.json.template
を変更してください。
新規jobの作成
最後に、生成したjob.json
を使用して、バッチのjobを登録します。
### Submit the job
echo "Submiting the job"
date=$(date +"%Y%m%d%H%M")
gcloud beta batch jobs submit pdf-compression_$date --location=us-central1 --config=$temp_dir/job.json
Job Nameには重複した値をつけることができないのでdate
を付加しています。
以上で、ファイル名の取得から、必要なファイルの生成、バッチへのjobの登録まで完了です。