GAEをweb cronとして使う

このエントリの和訳です。http://d.hatena.ne.jp/takahirox/20110430/1304145478

はじめに

以前のエントリでGAEがweb cronとして使えるのではないかと言及しました。
http://d.hatena.ne.jp/takahirox/20110425/1303732480

rubybotを作ったときcronの実現方法で悩んだことがありました。


http://d.hatena.ne.jp/takahirox/20090523/1243086497


恐らく「urllib2を使ったGAE python application」と「別のサーバにアップロードし、rubyや他の言語で作成した、CGIで起動するbotプログラム」を使えば、cronの問題が解決できるはずです。

それを実装してみたので、メモを残しておきます。

web cronを検討している人の参考になれば。

今回やったこと

botプログラムを好きなwebサーバにおいて、定期的にGAE applicationにそのbotプログラムを実行させました。つまりGAEをweb cronとして使ってみました。

作ったbot


このbotは定期的に現在時刻を呟くだけです。

特徴

  • 長所
    • pythonjavaの知識がなくてもbotが作れます
      • pythonjavaには存在しないrubyperlのライブラリを使用することができます
    • GAEに制約を受けなくて済みます
  • 短所
    • セキュリティの問題
      • botCGIで実行される必要があります
      • つまり、そのURLを叩けば誰でも実行できてしまいます
      • パスワードなどを設定して対処する必要があります

bot用のtwitterアカウントを取得する

最初にbot用のアカウントを取得します。そしてtokenやtoken secretも取得します。

ここでの説明は省略します。下記のエントリを参考にしてください。


今回は@supertimebotを再利用しました。以前bot用に取得したアカウントです。詳細はこちら。

好きなwebサーバでbotを作る

その後、botを好きなwebサーバ上で作ります。今回はxreaサーバの上でrubyを使って作りました。

xreaで同じbotを作りたければ、xrea上に自分用のrubygemsをインストールする必要があります。rubygemstwitterライブラリを使うからです。インストールの仕方は下記を参考にしてください。


また、今回作ったbotプログラムは、以前rubyで作ったtwitter用のクライアントを基に作成しています。


botプログラムのソースコードは以下です。

#!/usr/local/bin/ruby

# main.cgi

require 'rubygems'
require 'twitter'
require 'time'
require 'cgi'

OAUTH_CONSUMER_KEY    = 'your consumer token'
OAUTH_CONSUMER_SECRET = 'your consumer secret'
OAUTH_ACCESS_TOKEN    = 'your access token'
OAUTH_ACCESS_SECRET   = 'your access token secret'

PROXY_ADDR = nil

oauth = Twitter::OAuth.new( OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET )
oauth.authorize_from_access( OAUTH_ACCESS_TOKEN, OAUTH_ACCESS_SECRET )
base = Twitter::Base.new( oauth )
base.update Time.now

cgi = CGI.new
puts cgi.header
puts 'homuhomu.'

CGIで動くようにする必要があることに注意してください。(今回作ったbotのURLは秘密です)

GAEを設定する

最後に、GAE applicationにbotを実行させる設定をします。

bot用にGAE applicationを登録して、下記のファイルをデプロイします。

詳細はこちらのエントリで確認してください。


app.yaml

application: supertimebot
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: main.py

cron.yaml

cron:
- description: cron job name
  url: /.*
  schedule: every 20 minutes

main.py

import urllib2

urllib2.urlopen( 'your bot URL' )

成功すればbotが定期的に呟くはずです。

セキュリティについて

上述したように、セキュリティに気をつける必要があります。URLを叩けば誰でもそのbotを実行できてしまうからです。

対策としてすぐに思いつくのは以下でしょう。

  • パスワードを設定する
  • USER AGENTをチェックする
  • IPをチェックする
  • アクセスログを取る


こんな感じに。

#!/usr/local/bin/ruby

# main.cgi

require 'rubygems'
require 'twitter'
require 'time'
require 'cgi'

OAUTH_CONSUMER_KEY    = 'your consumer token'
OAUTH_CONSUMER_SECRET = 'your consumer secret'
OAUTH_ACCESS_TOKEN    = 'your access token'
OAUTH_ACCESS_SECRET   = 'your access token secret'

PROXY_ADDR = nil

if /\(\+http:\/\/code\.google\.com\/appengine; appid: supertimebot\)/ =~ ENV[ 'HTTP_USER_AGENT' ] then
  oauth = Twitter::OAuth.new( OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET )
  oauth.authorize_from_access( OAUTH_ACCESS_TOKEN, OAUTH_ACCESS_SECRET )
  base = Twitter::Base.new( oauth )

  base.update Time.now
end

cgi = CGI.new
puts cgi.header
puts 'homuhomu.'

f = File.open( './homu.txt', 'a' )
f.puts Time.now
ENV.each do |key, value|
  f.puts key, value
end
f.puts


USER AGENTをチェックしています。さらに、アクセスログを取っています。もちろん、これだけでは不十分ですが。

終わりに

botを好きなwebサーバで作ることができるようになりました。GAE, python, javaの知識はほとんど必要ありません。

しかし、セキュリティを考える必要があるので完全ではありません。