VPS にデーモンを常駐させて遊ぶ

さくらインターネットさんが値段を下げてにわかに活気づく VPS。

VPS のよいところは、root 権限があることで、もう Web サーバやら PHP やら MySQL やらの束縛からは解放されて、好きな言語や環境でインターネットのアプリケーションがつくれる環境が整いました。 🙂

たぶん VPS で動かして一番面白いのは、デーモンとして常駐してリアルタイムで処理を行うアプリケーション。 じゃーってことで、Groovy でやってみることにしましょう。

まずは UNIX Daemon のつくりかた。 C でやれば fork して tty 切り離してみたいな感じになるとおもいますが、ここは Groovy ってことで、JVM 上のアプリを daemon 扱いにしてシグナルをとばしてくれる Apache Commons の commons-daemon を使うとよいです。

Daemon : Java based daemons or services

Daemon is made of 2 parts. One written in C that makes the interface to the operating system and the other in Java that provides the Daemon API.

commons-daemon には jsvc という UNIX Daemon と Java を取り持つバイナリのソースが入っています。 まずはこれを VPS の環境なりでコンパイルします。 Java のホームディレクトリを指定して configure をかけるのがポイントです。

src/unix$ ./configure --with-java=/usr/lib/jvm/java-6-sun

make すると jsvc のバイナリができます。

次に Java でデーモン用のソースをかきます。 ここでは Groovy で。

org.apache.commons.daemon.Daemon を implements してシグナルハンドラと結びつく規定のインターフェースを実装してあげればOKです。 サービスクラスはスレッドにして、ちゃんと途中でとまるようにつくる感じになるでしょう。

ここではおなじみ twitter4j のストリーミング API をサービスクラスにしています。 VPS とは関係ないですが、ストリーミング API でうけたメッセージを Ubuntu の NotifyOSD で通知するサンプルです。 (画面ならデーモンじゃなくて UI スレッドでやれって感じですが、サンプルということで…)

package net.maple4ever.daemon import java.security.MessageDigest import org.apache.commons.daemon.* import org.apache.log4j.Logger import org.gnome.gtk.Gtk import org.gnome.gdk.Pixbuf import org.gnome.notify.Notify import org.gnome.notify.Notification import twitter4j.Status import twitter4j.TwitterFactory import twitter4j.TwitterStream import twitter4j.TwitterStreamFactory import twitter4j.User import twitter4j.UserStreamAdapter import twitter4j.conf.ConfigurationBuilder class TwitterDaemon implements Daemon { private static TwitterDaemon daemon = new TwitterDaemon() private static Logger logger = Logger.getLogger(TwitterDaemon.class) private TwitterStream stream = null // twitter oAuth 設定(取得して入れます) def consumer = "" def consumerSecret = "" def accessToken = "" def accessTokenSecret = "" @Override public void init(DaemonContext arg0) throws DaemonInitException, Exception { // twitter 認証設定 def builder = new ConfigurationBuilder() builder.setOAuthConsumerKey(consumer) builder.setOAuthConsumerSecret(consumerSecret) builder.setOAuthAccessToken(accessToken) builder.setOAuthAccessTokenSecret(accessTokenSecret) def config = builder.build() // GTK 初期化 Gtk.init([] as String[]) Notify.init("notify.groovy") // Strinming API 取得 def twitter = new TwitterFactory(config).getInstance() stream = new TwitterStreamFactory(config).getInstance( twitter.getOAuthAccessToken()) // Strinming API イベント登録 stream.addListener(new UserStreamAdapter() { @Override public void onStatus(Status status) { User user = status.getUser() def url = user.getProfileImageURL() def screenname = user.getScreenName() def text = status.getText() try { // twitter アイコン取得 MessageDigest md5 = MessageDigest.getInstance("MD5") def md5str md5.with { md5str = new BigInteger( 1, digest(new File(url.file).name.bytes)) .toString(16).padLeft(32, '0') } def filename = "/tmp/" + md5str File file = new File(filename) if(!file.exists()) { file << url.getBytes() } def pixbuf = new Pixbuf( filename, 40, 40, true) // NotifyOSD 通知 def notify = new Notification( "@${screenname}", "${text}", null) notify.setIcon(pixbuf) notify.show() } catch (e) { logger.error(e.message) } } }) } @Override public void start() throws Exception { stream.user() } @Override public void stop() throws Exception { stream.cleanUp() } @Override public void destroy() { } static main(args) { daemon.init(null) daemon.start() } }

# こんなの動かす人いないと思いますが、GTK-Java のライブラリ jar は sudo apt-get install libjava-gnome-java で /usr/share/java かその辺に入ると思います。

デーモンではなく、通常実行でも動作させてデバッグしやすいように static main(args) もいれています。

で、できたら次のように jsvc にクラスを渡してデーモン化してもらいます。

/opt/twitter-daemon/bin/jsvc-ubuntu \ -pidfile /opt/twitter-daemon/bin/TwitterDaemon.pid \ -user hiromasa \ -home /usr/lib/jvm/java-6-sun/ \ -cp /opt/twitter-daemon/lib/*:/opt/twitter-daemon/classes \ -Dlog.home=/opt/twitter-daemon/logs/TwitterDaemon.log \ -Dstream.user.repliesAll=false \ net.maple4ever.daemon.TwitterDaemon

次のように Java のプロセスが 2つ常駐すれば成功です。

hiromasa 6975 1 0 23:09 ? 00:00:00 jsvc.exec -pidfile hiromasa 6976 6975 17 23:09 ? 00:00:01 jsvc.exec -pidfile

NotifyOSD で twitter の投稿がリアルタイムに通知されてきます。 🙂

moz-notify

停止は以下のようにします。 start / stop/ restart 用のシェルをつくることになるでしょう。

/opt/twitter-daemon/bin/jsvc-ubuntu \ -stop \ -pidfile /opt/twitter-daemon/bin/TwitterDaemon.pid \ net.maple4ever.daemon.TwitterDaemon

ここではソースのサンプルとして画面通知にしてしまっていますが、たとえば twitter 関係で VPS で動かすようなものなら、 bot 的なものも cron とかの無理な方法をとることなく簡単に扱いやすいアプリケーションが作れると思います。

常時インターネットにつながっている VPS でリアルタイム処理ができるのは、いろいろ夢が広がりますね。

GroovyClassLoader をうまくつかって Java と Groovy のインターフェースをつくってあげれば、スクリプトテキストファイルのまま、コンパイルすることなくデーモンをつくるようなことも可能です。

daemon

え、最後のそれ、らい子ちゃんを載せたかっただけだろって、、、。はい。 orz

コメントを残す