以前作成した映画情報取得用スクリプトのように
定期的に実行したいスクリプトを作成した場合、
そのスクリプトをどこで動かすか、というのが悩みどころになる。
いくつか方法はあるのだけど、
ローカルのPCでタスクスケジューラなりcronなりで動かす方法は
無料だし手軽にできるけど、実行したい時間にPCを起動しておく必要がある。
さくらインターネット等のVPSを借りてcronで動かす方法は
費用はそんなに高くないけど、ファイアウォールの設定等
安心して使える環境を作るまでのハードルが結構高い。
一昔前はそこで頑張ってVPSを立てるか、諦めるかしかなかったのだけど、
今はそんな時のためのサーバーレス(=サーバ管理のいらない)なサービスが使える。
今回は AWS の AWS Lambda を使って、
作成したスクリプトを定期実行する環境を作ってみたい。
AWS Lambda とは
AWS Lambda は上記の説明に記載があるとおり、
なにがしかのスクリプトを作って、
それを実行する条件となるトリガーを設定しておくと、
そのトリガーが発動した時にスクリプトを実行してくれるサービス。
トリガーは例えば、
「指定したテーブルのデータが更新された」「指定した日時になった」
みたいなものが多数用意されているので、そこから選択する。
HTTPリクエストをトリガーとしてJSONやHTMLを返すような
Webアプリ的な使い方もできるけど、
Webアプリのように常時立ち上がっているものではなく、
呼び出されて初めて起動し、実行される。
イベントが発生しなければ費用も発生しない。
そして、 AWS Lambda の場合は100万回/月の実行まで無料で利用可能。
つまり、月に数回から数十回定期的に実行するようなスクリプトなら
無料枠内で試せるので、自動化を始めるには非常に適したサービスになっている。
ハードルがあるとしたら、
AWSにLambda以外にもサービスがたくさんあったり、色々細かく設定できすぎて、
慣れるまで何をどうしたらよいか分からない、というところくらい。
まずは読み進める前にAWSのアカウントを取得して、
操作用のIAMアカウントを作成し、
AWSのサービス管理画面にログインするところまで頑張ろう。
AWS Lambda 関数を作成する
AWSのサービス管理画面にログインできたら、
下記の手順で関数を実行できる環境を作る。
- スクリプトを作成する
- AWS Lambda の関数作成画面でスクリプトを登録する
- テストする
- トリガーを追加する
スクリプトを作成する
AWS Lambda 用のスクリプトは、
関数作成画面で直接編集する方法と、
ローカルで作成して必要なファイルをzipでまとめてアップロードする方法がある。
標準以外のライブラリを使用する場合は後者のzipアップロードの方法を
使う必要があるので、こちらで進める。
AWS Lambda はイベントハンドラとなる関数を定義しておくことで、
トリガーが発火した時にその関数を実行してくれる仕組みになっている。
上述の「映画情報取得用スクリプト」の記事で作成した
メイン実行用ファイルは下記のように作成していたが、
const slack = require('./slack'); const movieScrape = require('./movie_scrape'); async function main() { const scheduleList = await movieScrape.fetch(); const scheduleListText = movieScrape.stringifyList(scheduleList); const slackMessageText = "<映画情報>\n\n" + scheduleListText; const token = "<APIトークン>"; await slack.postMessage(token, "#general", slackMessageText); } main();
AWS Lambda で実行する場合は下記のようにメイン関数をexportする形の
メイン実行用ファイルを作成する。
const slack = require('./slack'); const movieScrape = require('./movie_scrape'); exports.handler = async (event) => { const scheduleList = await movieScrape.fetch(); const scheduleListText = movieScrape.stringifyList(scheduleList); const slackMessageText = "<映画情報>\n\n" + scheduleListText; const token = "<APIトークン>"; await slack.postMessage(token, "#general", slackMessageText); return { statusCode: 200, body: '' }; }
このファイルを「lambda.js」として作成したとしよう。
作成したら、これを必要なファイルとともにzipファイルにまとめる。
必要なのは、自作のjsファイルとnode_modulesフォルダ。
Macなら下記のようなコマンドで「fetch_tv_movies.zip」というファイルを作成できる。
zip -r fetch_tv_movies.zip lambda.js slack.js movie_scrape.js node_modules
うまく実行できなかったら何度もzip化することになるので、
シェルスクリプトにでもまとめておく。
zipファイル名は適当で良いけどlambda関数名と合わせておくのが良いかも。
AWS Lambda の関数作成画面でスクリプトを登録する
AWS Lambda 関数を登録する準備が整ったので、
AWS マネジメントコンソールにIAMアカウントでログインして登録処理を行う。
ログインして Lambda メニューを選択し、
Lambda の管理画面に遷移して「関数の作成」ボタンをクリックすると
関数の作成画面に遷移する。
そこで下記のように好きな関数名をつけて、ランタイムに「Node.js 8.10」を選択して、
実行ロールについて今回は特にログ保存以外のAWSサービスを使用しないので
「テンプレートから新しいロールを作成」を選択し、
「lambda_basic」みたいな名前をつけて
関数を作成する。
関数の作成に成功すると、トリガーやスクリプトの登録ができる設定画面に遷移する。
とりあえず必要なのが関数コードの登録。
ここでzipファイルをアップロードする。
その際、ハンドラには先程作成した
メイン実行用ファイル名(lambda.jsのlambda)と
ハンドラ名(exports.handlerのhandler)を組み合わせて
「lambda.handler」を設定しておく。
今回のスクリプトはWebスクレイピングとAPI接続を伴うので、
「基本設定」でタイムアウトを「30秒」に延ばしておく。
テストする
トリガーを追加する前にアップロードしたスクリプトがちゃんと実行できるか、
テストしておこう。
テストは「テストイベント」設定でスクリプトに渡すパラメータを指定しておき、
それを実行する形で行う。
画面右上の「テスト」メニューでテストイベントの設定ができる。
今回のスクリプトはパラメータを受け取らないので、
「NoParamTest」みたいな名前で「{}」を保存しておけばOK。
作成したテストイベントはプルダウン選択できるようになるので、
「NoParamTest」を選択して「テスト」ボタンを実行すると関数が実行される。
それで成功メッセージが表示されてSlackに投稿が行われたら問題なし。
トリガーを追加する
最後に、この関数を実行するためのトリガーを登録する。
ひとまず、「指定時実行」と「URLアクセス時の実行」の
2つの方法を押さえておけば大抵事足りると思うので、この2つの方法について書いておく。
トリガーの登録は編集画面上部の「トリガーの追加」ブロックで行う。
「指定時実行」する場合は「CloudWatch Events」を選択する。
選択すると下に編集フォームが表示されるので、ここで細かい設定を行う。
例えば「毎週月曜0時0分」に実行したい場合、下記のように設定する。
ルール名は分かりやすい名前をつけておく。
時間はUTCなので実際に必要な時間の9時間前にセットしておく。
月曜0時なら日曜15時かな。
スケジュール式の設定方法は下記のヘルプページに記載されている。
ルールのスケジュール式 - Amazon CloudWatch Events
これで追加しておけばOK。
次に「URLアクセス時に実行」する場合は「API Gateway」を使用する。
選択すると下記のような編集フォームが表示される。
API項目で「新規APIの作成」を選択するとセキュリティ項目が表示され、
APIへのアクセスにどのような認証を必要とするかを選択できる。
「AWSIAM」はIAM認証だと思うけど試してない。
「オープン」は認証なし。APIのURLにアクセスするだけで実行できる。
「APIキー使用でのオープン」は正しいAPIキー付きでアクセスした場合だけ実行できる。
今回は「APIキー使用でのオープン」を選択するとする。
アクセス用のURLとAPIキーは追加時に生成される。
APIキー付きのアクセスはリクエスト時のヘッダーに
「x-api-key」という名称でAPIキーをつけてアクセスする。
curlなら下記のような形
curl https://<APIのURL> --header 'x-api-key:<APIキー>'
これで実行してSlackに投稿されたら登録に成功してる。
これでトリガー登録完了で、Lambda関数の登録完了。
おわり
説明は長くなったけど、1つ作ってしまえば他のスクリプトの登録も
そんなに難しくないと思う。
データベースにデータを保存したり、ファイルを入出力する場合は
追加の設定が必要だけど、ちょっとしたデータ収集、変換と通知なら対応できるはず。
- 作者: 大澤文孝
- 出版社/メーカー: インプレス
- 発売日: 2017/10/16
- メディア: Kindle版
- この商品を含むブログを見る