id:winebarrelさんのエントリ や西谷さんのエントリに書かれている通り、Nodeからプロセスを起動すれば、任意のコマンドが実行できるようです。
exports.handler = function(event, context) { var child_process = require('child_process'); child_process.exec("java -version", function(err, stdout, stderr) { console.log(stderr) context.done(); }) };
結果
Logs ---- START RequestId: 63c680fd-757e-11e4-b378-096fa7a78a98 2014-11-26T15:10:31.563Z 63c680fd-757e-11e4-b378-096fa7a78a98 java version "1.7.0_71" OpenJDK Runtime Environment (amzn-2.5.3.0.51.amzn1-x86_64 u71-b14) OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode) END RequestId: 63c680fd-757e-11e4-b378-096fa7a78a98 REPORT RequestId: 63c680fd-757e-11e4-b378-096fa7a78a98 Duration: 1619.27 ms Billed Duration: 1700 ms Memory Size: 128 MB Max Memory Used: 16 MB
java version "1.7.0_71"、素晴らしい。Eric先生のエントリにも細かく書いていますね。
Lambdaは/tmpに512MBまでのファイルが置けるので、これを使って、S3上に置いたJarファイルからJavaを起動するwrapperを書きました。
適当なS3 bucket上にjarを並べて、バケット名、リージョン、起動クラスを指定すればブートします。
プロセス起動はこちらを参考にしました。
var aws = require('aws-sdk'); var fs = require('fs'); var javaBucket = "lambda-java"; var javaBucketRegion = "us-west-2"; var mainClass = "Main2"; exports.handler = function(event, context) { loadAllFiles(function() { var spawn = require('child_process').spawn; var child = spawn('java', [ "-cp", "/tmp:/tmp/*", mainClass, JSON.stringify(event,null,2) ]); child.stdout.on('data', function(data) { console.log("stdout:" + data); }); child.stderr.on('data', function(data) { console.log("stderr:" + data); }); child.on('close', function(code) { context.done(null, 'end'); }); }); }; function loadAllFiles(callback) { var s3 = new aws.S3({ region : javaBucketRegion }); s3.listObjects({ Bucket : javaBucket }, function(err, data) { if (err) { throw err; } else { var cb = createCounter(data.Contents.length, callback); for (var i = 0; i < data.Contents.length; i++) { loadObject(cb, data.Contents[i].Key); } } }); } function loadObject(callback, key) { var s3 = new aws.S3({ region : javaBucketRegion }); s3.getObject({ Bucket : javaBucket, Key : key }, function(err, data) { if (err) { throw err; } else { console.log("load:" + key); fs.writeFileSync('/tmp/' + key, data.Body); callback(); } }); } function createCounter(length, callback) { var counter = 0; return function() { if (++counter == length) { callback(); } } }
ためしにTomcatをS3上に置いて起動してみます。
結果
Logs ---- START RequestId: 026ef527-757f-11e4-8cf1-c193c778b689 2014-11-26T15:14:55.796Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-embed-jasper.jar 2014-11-26T15:14:55.842Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-dbcp.jar 2014-11-26T15:14:55.880Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-embed-el.jar 2014-11-26T15:14:55.921Z 026ef527-757f-11e4-8cf1-c193c778b689 load:hoge2.jar 2014-11-26T15:14:55.940Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-embed-logging-juli.jar 2014-11-26T15:14:55.979Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat7-embed-websocket.jar 2014-11-26T15:14:56.019Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-embed-logging-log4j.jar 2014-11-26T15:14:56.456Z 026ef527-757f-11e4-8cf1-c193c778b689 load:tomcat-embed-core.jar 2014-11-26T15:15:05.480Z 026ef527-757f-11e4-8cf1-c193c778b689 stderr:Nov 26, 2014 7:15:05 AM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-bio-8080"] 2014-11-26T15:15:05.601Z 026ef527-757f-11e4-8cf1-c193c778b689 stderr:Nov 26, 2014 7:15:05 AM org.apache.coyote.AbstractProtocol init SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-8080"] java.net.BindException: Operation not permitted <null>:8080 at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:411) at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:646)
8080へのbind処理が失敗しましたが、ブートすることが確認できました。headlessオプション付ければ描画もいけると思うので、次はサーバサイド描画を試してみます。